Compare commits

...

61 Commits

Author SHA1 Message Date
syuilo
4c97b847e7 10.55.0 2018-11-18 12:00:07 +09:00
syuilo
cfa4f0fe0b Add zh-CN 2018-11-18 11:59:26 +09:00
syuilo
9672343360 New Crowdin translations (#3255)
* New translations ja-JP.yml (Catalan)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Portuguese)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Dutch)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (Catalan)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Portuguese)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Dutch)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Catalan)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Portuguese)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Dutch)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (Catalan)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Portuguese)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Dutch)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Catalan)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Portuguese)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Dutch)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Catalan)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Portuguese)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Dutch)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Chinese Simplified)
2018-11-18 10:56:51 +09:00
Zero King
80fdfe54c4 Add faUserClock icon for follow requests (#3303) 2018-11-18 01:10:57 +09:00
MeiMei
7fcbe87591 Improve relative time detection (#3302) 2018-11-17 20:57:23 +09:00
MeiMei
e401ba9e25 Update visibility text (#3299) 2018-11-17 18:21:05 +09:00
MeiMei
35db61f1b4 To able to store local only visibilities (#3298) 2018-11-17 13:21:40 +09:00
syuilo
6c72545fc8 [Test] Add a test and some updtes 2018-11-17 12:52:20 +09:00
dependabot[bot]
70385ca670 Update @types/webpack requirement from 4.4.18 to 4.4.19 (#3295)
Updates the requirements on [@types/webpack](https://github.com/DefinitelyTyped/DefinitelyTyped) to permit the latest version.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-17 05:30:30 +09:00
dependabot[bot]
a8e72d39f7 Update vue-svg-inline-loader requirement from 1.2.1 to 1.2.2 (#3294)
Updates the requirements on [vue-svg-inline-loader](https://github.com/oliverfindl/vue-svg-inline-loader) to permit the latest version.
- [Release notes](https://github.com/oliverfindl/vue-svg-inline-loader/releases)
- [Commits](https://github.com/oliverfindl/vue-svg-inline-loader/commits/v1.2.2)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-17 05:30:18 +09:00
MeiMei
0bf54b3ff6 Renote visibility (#3290) 2018-11-17 03:25:48 +09:00
MeiMei
db657c2a62 Hide unused login method (#3285) 2018-11-17 02:13:01 +09:00
nico
01964f3926 Add missing Robot icon (used on user profiles) (#3284) 2018-11-17 01:55:37 +09:00
nico
bfd6bb0fda Add missing Map Marker icon (used on user profiles) (#3283) 2018-11-17 01:50:39 +09:00
Aya Morisawa
3fc70996e2 Change math syntax (#3280) 2018-11-17 00:31:49 +09:00
syuilo
cb0874f15a 10.54.0 2018-11-16 23:19:34 +09:00
Aya Morisawa
9239e37b45 Fix #3273 (#3277) 2018-11-16 23:14:11 +09:00
Aya Morisawa
57d80932a4 Add an optional setting to remain deleted note (#3271)
Co-authored-by: Aya Morisawa <AyaMorisawa4869@gmail.com>
Co-authored-by: syuilo <syuilotan@yahoo.co.jp>
2018-11-16 23:13:37 +09:00
syuilo
8569970fbe Update github-bot.ts 2018-11-16 23:10:48 +09:00
syuilo
713e9ad5f4 Resolve #3274 2018-11-16 23:09:33 +09:00
syuilo
59e229d962 Update github-bot.ts 2018-11-16 23:02:01 +09:00
syuilo
3c5f09cda2 Clean up 2018-11-16 23:01:14 +09:00
syuilo
e42aa2530d Update github-bot.ts
follow dvelop instead master
2018-11-16 23:00:34 +09:00
Zero King
1fd298ac9c Update docker.en.md (#3272) 2018-11-16 22:47:10 +09:00
syuilo
1a73f52541 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-11-16 22:32:17 +09:00
syuilo
27e458f884 Do not use camelCase in html 2018-11-16 22:32:06 +09:00
Zero King
ba3e2a9371 Update setup.en.md (#3270)
* [doc] run as root

* [doc] update setup guide headings
2018-11-16 22:31:53 +09:00
syuilo
831e8f8583 Refactoring 2018-11-16 22:31:28 +09:00
syuilo
0ff390ed80 [MFM] Improve various parsing
Resolve #2779
Resolve #3053
2018-11-16 21:57:19 +09:00
syuilo
e3b8495431 [MFM] Better URL parsing 2018-11-16 21:30:01 +09:00
syuilo
da10ba3fea [Client] Add missing icon
Resolve #3267
2018-11-16 18:34:52 +09:00
syuilo
cc7de853b4 [Client] Wrap formula component to split code 2018-11-16 18:31:25 +09:00
syuilo
23d8235197 Revert "[Client] Load katex async to reduce bundle size"
This reverts commit 37e3d60ade.
2018-11-16 18:26:19 +09:00
syuilo
37e3d60ade [Client] Load katex async to reduce bundle size 2018-11-16 18:22:44 +09:00
syuilo
83a3426dd5 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-11-16 17:56:08 +09:00
syuilo
a2549192ca Update misskey-flavored-markdown.ts 2018-11-16 17:55:48 +09:00
Aya Morisawa
9d3a1cab6e Fix #3224 (#3265) 2018-11-16 17:41:52 +09:00
Aya Morisawa
06f8d8f0a3 Show server version on server.info.vue (#3264) 2018-11-16 17:24:03 +09:00
MeiMei
fa66b79e2d Update the locale when version or language changed (#3263) 2018-11-16 17:13:22 +09:00
Aya Morisawa
81312f5a93 Remove a trailing whitespace (#3261) 2018-11-16 17:04:28 +09:00
Aya Morisawa
ad84901f39 Support math rendering on MFM (#3260) 2018-11-16 17:03:52 +09:00
MeiMei
d2385a0e52 Do not show duplicate url-preview (#3259) 2018-11-16 16:35:13 +09:00
syuilo
39285fc2d0 10.53.0 2018-11-16 05:56:58 +09:00
syuilo
6e491c1466 Refactoring 2018-11-16 05:53:17 +09:00
dependabot[bot]
84152aa663 Update typescript-eslint-parser requirement from 20.1.1 to 21.0.0 (#3237)
Updates the requirements on [typescript-eslint-parser](https://github.com/eslint/typescript-eslint-parser) to permit the latest version.
- [Release notes](https://github.com/eslint/typescript-eslint-parser/releases)
- [Changelog](https://github.com/eslint/typescript-eslint-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/typescript-eslint-parser/commits/v21.0.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-16 05:49:21 +09:00
dependabot[bot]
600fc65c2f Update showdown requirement from 1.8.7 to 1.9.0 (#3252)
Updates the requirements on [showdown](https://github.com/showdownjs/showdown) to permit the latest version.
- [Release notes](https://github.com/showdownjs/showdown/releases)
- [Changelog](https://github.com/showdownjs/showdown/blob/master/CHANGELOG.md)
- [Commits](https://github.com/showdownjs/showdown/commits/1.9.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-16 05:49:07 +09:00
dependabot[bot]
40e2733424 Update mongodb requirement from 3.1.8 to 3.1.9 (#3253)
Updates the requirements on [mongodb](https://github.com/mongodb/node-mongodb-native) to permit the latest version.
- [Release notes](https://github.com/mongodb/node-mongodb-native/releases)
- [Changelog](https://github.com/mongodb/node-mongodb-native/blob/master/HISTORY.md)
- [Commits](https://github.com/mongodb/node-mongodb-native/commits/v3.1.9)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-16 05:48:39 +09:00
MeiMei
bceb02d760 local only visibility (#3254)
* local only visibility

* fix UI
2018-11-16 05:47:29 +09:00
syuilo
aaaaf2681a [Client] Add missing icon 2018-11-16 05:38:16 +09:00
syuilo
3c3ef9bba0 [Client] ✌️ 2018-11-16 05:36:52 +09:00
syuilo
338f3a981f Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-11-16 05:26:48 +09:00
syuilo
a86ae9fa50 Better UX 2018-11-16 05:26:36 +09:00
syuilo
a3c4e8a1bc [Client] Improve admin dashboard 2018-11-16 05:21:52 +09:00
syuilo
6a7c18e8db Merge pull request #3250 from syuilo/l10n_develop
New Crowdin translations
2018-11-16 05:10:41 +09:00
syuilo
672b7a4c3d 🎨 2018-11-16 05:07:59 +09:00
MeiMei
bf3fee4481 Check the port is configured (#3251) 2018-11-16 03:25:35 +09:00
syuilo
a3c8d1d732 New translations ja-JP.yml (Chinese Simplified) 2018-11-16 00:15:45 +09:00
syuilo
bb03d8c49a New translations ja-JP.yml (Chinese Simplified) 2018-11-15 23:59:41 +09:00
syuilo
fbd5abe3b6 New translations ja-JP.yml (Chinese Simplified) 2018-11-15 23:43:21 +09:00
syuilo
5ac390abe9 New translations ja-JP.yml (Chinese Simplified) 2018-11-15 23:38:10 +09:00
Aya Morisawa
766cae2299 Check Node.js version (#3245)
* Check Node.js version

* Fix bug
2018-11-15 22:17:06 +09:00
70 changed files with 1971 additions and 1408 deletions

View File

@@ -13,7 +13,7 @@ This guide describes how to install and setup Misskey with Docker.
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
*2.* Configure Misskey
----------------------------------------------------------------
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`.
@@ -31,12 +31,12 @@ Build misskey with the following:
*5.* That is it.
----------------------------------------------------------------
Well done! Now, you have an environment that run to Misskey.
Well done! Now you have an environment to run Misskey.
### Launch normally
Just `docker-compose up -d`. GLHF!
### Way to Update to latest version of your Misskey
### How to update your Misskey server to the latest version
1. `git fetch`
2. `git stash`
3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)`
@@ -45,9 +45,9 @@ Just `docker-compose up -d`. GLHF!
6. Check [ChangeLog](../CHANGELOG.md) for migration information
7. `docker-compose stop && docker-compose up -d`
### Way to execute cli command:
### How to execute [cli commands](manage.en.md):
`docker-compose run --rm web node cli/mark-admin @example`
----------------------------------------------------------------
If you have any questions or troubles, feel free to contact us!
If you have any questions or trouble, feel free to contact us!

View File

@@ -10,7 +10,7 @@ This guide describes how to install and setup Misskey.
*1.* Create Misskey user
----------------------------------------------------------------
Running misskey on root is not a good idea so we create a user for that.
Running misskey as root is not a good idea so we create a user for that.
In debian for exemple :
```
@@ -32,7 +32,7 @@ Please install and setup these softwares:
*3.* Setup MongoDB
----------------------------------------------------------------
In root :
As root:
1. `mongo` Go to the mongo shell
2. `use misskey` Use the misskey database
3. `db.users.save( {dummy:"dummy"} )` Write dummy data to initialize the db.
@@ -47,17 +47,17 @@ In root :
4. `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)
5. `npm install` Install misskey dependencies.
*(optional)* Generating VAPID keys
*(optional)* Generate VAPID keys
----------------------------------------------------------------
If you want to enable ServiceWorker, you need to generate VAPID keys:
Unless you have set your global node_modules location elsewhere, you need to run this in root.
Unless you have set your global node_modules location elsewhere, you need to run this as root.
``` shell
npm install web-push -g
web-push generate-vapid-keys
```
*5.* Make configuration file
*5.* Configure Misskey
----------------------------------------------------------------
1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`.
2. Edit `default.yml`
@@ -114,7 +114,7 @@ WantedBy=multi-user.target
You can check if the service is running with `systemctl status misskey`.
### Way to Update to latest version of your Misskey
### How to update your Misskey server to the latest version
1. `git fetch`
2. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)`
3. `npm install`

View File

@@ -90,6 +90,9 @@ common:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
note-placeholders:
a: "今どうしてる?"
b: "何かありましたか?"
@@ -427,6 +430,10 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-public-desc: "リモートへは公開しない"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
@@ -676,6 +683,7 @@ desktop/views/components/post-form.vue:
create-poll: "アンケートを作成"
text-remain: "残り{}文字"
recent-tags: "最近"
local-only-message: "この投稿はローカルにのみ公開されます"
click-to-tagging: "クリックでタグ付け"
visibility: "公開範囲"
geolocation-alert: "お使いの端末は位置情報に対応していません"
@@ -693,6 +701,7 @@ desktop/views/components/renote-form.vue:
quote: "引用する..."
cancel: "キャンセル"
renote: "Renote"
renote-home: "Renote (Home)"
reposting: "しています..."
success: "Renoteしました"
failure: "Renoteに失敗しました"
@@ -707,6 +716,7 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "通知"
apps: "アプリ"
tags: "ハッシュタグ"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
@@ -749,6 +759,7 @@ desktop/views/components/settings.vue:
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
remain-deleted-note: "削除された投稿を表示し続ける"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
@@ -921,7 +932,7 @@ admin/views/index.vue:
emoji: "カスタム絵文字"
moderators: "モデレーター"
users: "ユーザー"
update: "更新"
federation: "連合"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
back-to-misskey: "Misskeyに戻る"

View File

@@ -90,6 +90,9 @@ common:
specified: "Direkt"
specified-desc: "Nur für bestimmte Benutzer posten"
private: "Privat"
local-public: "公開 (ローカルのみ)"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
note-placeholders:
a: "Was machst du gerade?"
b: "Was ist so passiert?"
@@ -427,6 +430,10 @@ common/views/components/visibility-chooser.vue:
specified: "Direkt"
specified-desc: "Poste nur für bestimmte Benutzer"
private: "Privat"
local-public: "公開 (ローカルのみ)"
local-public-desc: "リモートへは公開しない"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
@@ -676,6 +683,7 @@ desktop/views/components/post-form.vue:
create-poll: "Eine Abstimmung erstellen"
text-remain: "{} Zeichen verbleibend"
recent-tags: "最近"
local-only-message: "この投稿はローカルにのみ公開されます"
click-to-tagging: "クリックでタグ付け"
visibility: "Sichtbarkeit"
geolocation-alert: "お使いの端末は位置情報に対応していません"
@@ -693,6 +701,7 @@ desktop/views/components/renote-form.vue:
quote: "Zitieren..."
cancel: "Abbrechen"
renote: "Anmerkung"
renote-home: "Renote (Home)"
reposting: "Weitersagen..."
success: "Weitergesagt!"
failure: "Weitersagen fehlgeschlagen"
@@ -707,6 +716,7 @@ desktop/views/components/settings.vue:
profile: "Profil"
notification: "Mitteilungen"
apps: "In App öffnen"
tags: "ハッシュタグ"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "Sicherheit"
@@ -749,6 +759,7 @@ desktop/views/components/settings.vue:
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Karte anzeigen"
remain-deleted-note: "削除された投稿を表示し続ける"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
@@ -921,7 +932,7 @@ admin/views/index.vue:
emoji: "カスタム絵文字"
moderators: "モデレーター"
users: "ユーザー"
update: "更新"
federation: "連合"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
back-to-misskey: "Misskeyに戻る"

View File

@@ -90,6 +90,9 @@ common:
specified: "Direct"
specified-desc: "Post to specified users only"
private: "Private"
local-public: "Local (Public)"
local-home: "Local (Home)"
local-followers: "Local (Followers)"
note-placeholders:
a: "What are you doing?"
b: "What's happening?"
@@ -427,6 +430,10 @@ common/views/components/visibility-chooser.vue:
specified: "Direct"
specified-desc: "Post to specified users only"
private: "Private"
local-public: "Local (Public)"
local-public-desc: "Do not publish to remote"
local-home: "Local (Home)"
local-followers: "Local (Followers)"
common/views/components/trends.vue:
count: "{} users mentioned"
empty: "No popular hashtag trends"
@@ -676,6 +683,7 @@ desktop/views/components/post-form.vue:
create-poll: "Create a poll"
text-remain: "{} characters remaining"
recent-tags: "Recent"
local-only-message: "This post will only be published locally"
click-to-tagging: "Click to tagging"
visibility: "Visibility"
geolocation-alert: "Your device does not provide location services."
@@ -693,6 +701,7 @@ desktop/views/components/renote-form.vue:
quote: "Quote..."
cancel: "Cancel"
renote: "Repost"
renote-home: "Renote (Home)"
reposting: "Reposting..."
success: "Reposted!"
failure: "Failed to Repost"
@@ -707,6 +716,7 @@ desktop/views/components/settings.vue:
profile: "Profile"
notification: "Notification"
apps: "Apps"
tags: "Hashtags"
mute-and-block: "Mute / Block"
blocking: "Blocking"
security: "Security"
@@ -749,6 +759,7 @@ desktop/views/components/settings.vue:
show-renoted-my-notes: "Show renoted posts of mine in timelines"
show-local-renotes: "Show renoted local posts in timelines"
show-maps: "Display a map to show the location"
remain-deleted-note: "Continue to show deleted posts"
deck-column-align: "Deck column alignment"
deck-column-align-center: "Center"
deck-column-align-left: "Left"
@@ -919,9 +930,9 @@ admin/views/index.vue:
dashboard: "Dashboard"
instance: "Instance"
emoji: "Emoji"
moderators: "Moderator"
moderators: "Moderators"
users: "Users"
update: "Update"
federation: "Federation"
announcements: "Announcements"
hashtags: "Hashtags"
back-to-misskey: "Back to Misskey"
@@ -976,8 +987,8 @@ admin/views/instance.vue:
proxy-account-username-desc: "Specify the user name of the account that is used as a proxy."
proxy-account-warn: "You must make an account having this username before this action."
max-note-text-length: "Maximum numbers of post characters"
disable-registration: "Stop user registration"
disable-local-timeline: "Make Local Timeline disabled"
disable-registration: "Disable new user registration"
disable-local-timeline: "Disable the Local Timeline"
invite: "Invite"
save: "Save"
saved: "Saved"
@@ -1424,7 +1435,7 @@ deck:
deck/deck.tl-column.vue:
is-media-only: "Only media posts"
is-media-view: "Media view"
edit: "Option"
edit: "Options"
deck/deck.user-column.vue:
posts: "Posts"
following: "Following"

View File

@@ -90,6 +90,9 @@ common:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
note-placeholders:
a: "¿Qué haces?"
b: "¿Qué está pasando?"
@@ -427,6 +430,10 @@ common/views/components/visibility-chooser.vue:
specified: "Directo"
specified-desc: "Publica solo para los seguidores que quieras"
private: "Privada"
local-public: "公開 (ローカルのみ)"
local-public-desc: "リモートへは公開しない"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
@@ -676,6 +683,7 @@ desktop/views/components/post-form.vue:
create-poll: "Crea una encuesta"
text-remain: "quedan {} caracteres"
recent-tags: "Reciente"
local-only-message: "この投稿はローカルにのみ公開されます"
click-to-tagging: "Click para etiquetar"
visibility: "Visibilidad"
geolocation-alert: "Tu dispositivo no tiene soporte de geolocalización."
@@ -693,6 +701,7 @@ desktop/views/components/renote-form.vue:
quote: "Cita..."
cancel: "Cancelar"
renote: "Volver a publicar"
renote-home: "Renote (Home)"
reposting: "Publicando de nuevo..."
success: "¡Publicado!"
failure: "La publicación ha fallado"
@@ -707,6 +716,7 @@ desktop/views/components/settings.vue:
profile: "Perfil"
notification: "Notificación"
apps: "Aplicaciones"
tags: "ハッシュタグ"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "Seguridad"
@@ -749,6 +759,7 @@ desktop/views/components/settings.vue:
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
remain-deleted-note: "削除された投稿を表示し続ける"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
@@ -921,7 +932,7 @@ admin/views/index.vue:
emoji: "カスタム絵文字"
moderators: "モデレーター"
users: "ユーザー"
update: "更新"
federation: "連合"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
back-to-misskey: "Misskeyに戻る"

View File

@@ -4,8 +4,8 @@ meta:
divider: ""
common:
misskey: "Une ⭐ du fédiverse"
about-title: "Une ⭐ du fédivers."
about: "Merci davoir choisis Misskey. Misskey est une <b>plateforme de micro-blogging distribuée</b> née sur Terre et fait partie du Fédiverse (un univers composé de diverses plateformes de réseaux sociaux organisées), elle est connectée mutuellement avec dautres plateformes de réseaux sociaux. Désirez-vous prendre une pause, un court instant, loin de lagitation de la ville et plonger dans un Internet dun nouveau genre ?"
about-title: "Une ⭐ du fédiverse."
about: "Merci davoir choisis Misskey. Misskey est une <b>plateforme de microblogage distribuée</b> née sur Terre et fait partie du Fédiverse (un univers composé de diverses plateformes de réseaux sociaux organisées), elle est connectée mutuellement avec dautres plateformes de réseaux sociaux. Désirez-vous prendre une pause, un court instant, loin de lagitation de la ville et plonger dans un Internet dun nouveau genre ?"
intro:
title: "Cest quoi Misskey ?"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
@@ -21,12 +21,12 @@ common:
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock:
detected: "Veuillez désactiver votre bloqueur de publicités"
warning: "<strong>Misskey n'utilise pas de publicités</strong>, mais quelques options peuvent être non disponibles ou fonctionneraient mal si un bloqueur de publicités est activé."
application-authorization: "Permissions de l'application"
warning: "<strong>Misskey nutilise pas de publicités</strong>, mais quelques options peuvent être non disponibles ou fonctionneraient mal si un bloqueur de publicités est activé."
application-authorization: "Autorisations de lapplication"
close: "Fermer"
do-not-copy-paste: "Veuillez ne pas entrer ou coller le code ici. Le compte peut être compromis."
load-more: "Charger plus"
got-it: "J'ai compris !"
got-it: "Jai compris !"
customization-tips:
title: "Conseils de personnalisation"
paragraph: "<p>ホームのカスタマイズでは、ウィジェットを追加/削除したり、ドラッグ&ドロップして並べ替えたりすることができます。</p><p>一部のウィジェットは、<strong><strong>右</strong>クリック</strong>することで表示を変更することができます。</p><p>ウィジェットを削除するには、ヘッダーの<strong>「ゴミ箱」</strong>と書かれたエリアにウィジェットをドラッグ&ドロップします。</p><p>カスタマイズを終了するには、右上の「完了」をクリックします。</p>"
@@ -44,8 +44,8 @@ common:
future: "à linstant"
just_now: "à l'instant"
seconds_ago: "Il y a {} seconde·s"
minutes_ago: "Il y a {} minute·s"
hours_ago: "Il y a {} heure·s"
minutes_ago: "Il y a {} min"
hours_ago: "Il y a {} h"
days_ago: "Il y a {} jours"
weeks_ago: "Il y a {} semaines·s"
months_ago: "Il y a {} mois"
@@ -90,6 +90,9 @@ common:
specified: "Direct"
specified-desc: "Publier uniquement aux utilisateurs·rices mentionnés·es"
private: "Privé"
local-public: "Local (Public)"
local-home: "Accueil (local uniquement)"
local-followers: "Local (Abonnés)"
note-placeholders:
a: "Que faites-vous maintenant ?"
b: "Quoi de neuf ?"
@@ -119,7 +122,7 @@ common:
do-not-use-in-production: 'Il sagit dune version de développement. Ne pas utiliser dans un environnement de production.'
is-remote-user: "Ces informations appartiennent à un·e utilisateur·rice distant·e."
is-remote-post: "Ceci est une publication distante."
view-on-remote: "Consulter le profil complet"
view-on-remote: " Consulter le profil complet"
error:
title: 'Une erreur est survenue'
retry: 'Réessayer'
@@ -158,15 +161,15 @@ common:
tips: "Conseils"
hashtags: "Hashtags"
dev: "Échec lors de la création de lapplication. Veuillez réessayer."
ai-chan-kawaii: "Ai-Chan est mignone !"
ai-chan-kawaii: "Ai-Chan est mignonne !"
auth/views/form.vue:
share-access: "Désirez-vous autoriser <i>{name}</i> à avoir accès à votre compte?"
permission-ask: "Cette application nécessite les autorisations suivantes :"
account-read: "Afficher les informations du compte :"
account-write: "Modifications des informations du compte :"
account-read: "Afficher les informations du compte."
account-write: "Modifications des informations du compte."
note-write: "Publier."
like-write: "Réagir aux publications."
following-write: "Sabonner et se désabonner."
following-write: "Suivre des comptes et se désabonner."
drive-read: "Lire votre Drive"
drive-write: "Téléverser/supprimer des fichiers dans votre Drive."
notification-read: "Lire vos notifications."
@@ -175,13 +178,13 @@ auth/views/form.vue:
accept: "Autoriser laccès"
auth/views/index.vue:
loading: "Chargement en cours"
denied: "L'autorisation de l'application a été refusée."
denied: "Lautorisation de lapplication a été refusée."
denied-paragraph: "Cette application ne va pas accéder à votre compte."
already-authorized: "Cette application est déjà autorisée"
already-authorized: "Cette application est déjà autorisée."
allowed: "Permissions autorisées de lapplication."
callback-url: "Retour vers l'application"
callback-url: "Retour vers lapplication."
please-go-back: "Veillez retourner à l'application."
error: "La session n'existe pas."
error: "La session nexiste pas."
sign-in: "Veuillez vous connecter"
common/views/components/games/reversi/reversi.vue:
matching:
@@ -229,7 +232,7 @@ common/views/components/games/reversi/reversi.room.vue:
common/views/components/connect-failed.vue:
title: "Échec de connexion au serveur"
description: "Il se peut quil y est un problème avec votre connexion internet, ou le serveur est hors-ligne ou en maintenance. Veuillez {réessayer} plus tard."
thanks: "On vous remercie d'utiliser Misskey."
thanks: "On vous remercie davoir choisi dutiliser Misskey."
troubleshoot: "Dépanner"
common/views/components/connect-failed.troubleshooter.vue:
title: "Dépannage"
@@ -254,8 +257,8 @@ common/views/components/media-banner.vue:
sensitive: "Contenu sensible"
click-to-show: "Cliquer pour afficher"
common/views/components/theme.vue:
light-theme: "Thème durant le mode clair"
dark-theme: "Thème durant le mode sombre"
light-theme: "Thème en mode jour"
dark-theme: "Thème en mode nuit"
light-themes: "Thème clair"
dark-themes: "Thème sombre"
install-a-theme: "Installer un thème"
@@ -297,7 +300,7 @@ common/views/components/messaging.vue:
no-history: "Pas d'historique"
common/views/components/messaging-room.vue:
empty: "Pas de conversations"
no-history: "Il n'y a pas plus d'historique"
no-history: "Aucun historique"
resize-form: "Faites glisser pour redimensionner"
new-message: "Nouveau message"
only-one-file-attached: "Un seul fichier peut être joint au message"
@@ -357,14 +360,14 @@ common/views/components/emoji-picker.vue:
common/views/components/signin.vue:
username: "Nom d'utilisateur·rice"
password: "Mot de passe"
token: "Token"
token: "Jeton"
signing-in: "Connexion…"
signin: "Se connecter"
or: "Ou"
signin-with-twitter: "Se connecter via Twitter"
signin-with-github: "Se connecter avec GitHub"
signin-with-discord: "Discordでログイン"
login-failed: "Échec d'authentification. Veuillez vérifier que votre nom d'utilisateur et mot de passe sont corrects."
signin-with-discord: "Se connecter avec Discord"
login-failed: "Échec dauthentification. Veuillez vérifier que votre nom dutilisateur et mot de passe sont corrects."
common/views/components/signup.vue:
invitation-code: "Code dinvitation"
invitation-info: "Si vous navez pas de code dinvitation, contactez un·e <a href=\"{}\">administrateur·rice</a>."
@@ -410,12 +413,12 @@ common/views/components/github-setting.vue:
connect: "Se connecter avec GitHub"
disconnect: "Déconnecter"
common/views/components/discord-setting.vue:
description: "お使いのDiscordアカウントをお使いのMisskeyアカウントに接続しておくと、プロフィールでDiscordアカウント情報が表示されるようになったり、Discordを用いた便利なサインインを利用できるようになります。"
connected-to: "次のDiscordアカウントに接続されています"
detail: "詳細..."
reconnect: "再接続する"
connect: "Discordと接続する"
disconnect: "切断する"
description: "Si vous liez votre compte Discord à votre compte Misskey, vous serez en mesure de voir votre compte Twitter s'afficher sur votre profil, vous aurez aussi la possibilité de vous connecter à Misskey en utilisant votre compte Discord."
connected-to: "Vous êtes connecté à votre compte Discord"
detail: "Détails …"
reconnect: "Reconnecter"
connect: "Lier votre compte Discord"
disconnect: "Déconnecter"
common/views/components/uploader.vue:
waiting: "Veuillez patienter"
common/views/components/visibility-chooser.vue:
@@ -427,6 +430,10 @@ common/views/components/visibility-chooser.vue:
specified: "Direct"
specified-desc: "Publier uniquement aux utilisateurs·rices mentionné·e·s"
private: "Privé"
local-public: "Local (Public)"
local-public-desc: "リモートへは公開しない"
local-home: "Accueil (local uniquement)"
local-followers: "Local (Abonnés)"
common/views/components/trends.vue:
count: "{} utilisateurs·rices mentionnés·es"
empty: "Aucune tendance"
@@ -456,9 +463,9 @@ common/views/widgets/broadcast.vue:
next: "Suivant"
common/views/widgets/calendar.vue:
year: "Année {}"
month: "{},"
day: "Jour {}"
today: "Aujourd'hui :"
month: "Mois {}"
day: "{}"
today: "Aujourdhui:"
this-month: "Ce mois-ci :"
this-year: "Cette année :"
common/views/widgets/donation.vue:
@@ -501,9 +508,9 @@ common/views/widgets/tips.vue:
tips-line19: "Plusieurs fenêtres peuvent être détachées en dehors du navigateur."
tips-line20: "Pourcentage sur le widget calendrier qui indique le pourcentage de temps passé"
tips-line21: "Vous pouvez aussi utiliser l'API pour développer des Bots."
tips-line23: "Mayu est mignone avec ses sourcils."
tips-line24: "Misskey a vu le jour en 2014"
tips-line25: "対応ブラウザではMisskeyを開いていなくても通知を受け取れます"
tips-line23: "Mayu est mignonne avec ses sourcils."
tips-line24: "Misskey est fonctionnel depuis 2014"
tips-line25: "Vous pouvez recevoir les notifications de Misskey dans un navigateur web compatible"
common/views/pages/follow.vue:
signed-in-as: "Connecté·e en tant que {}"
following: "Suit"
@@ -515,12 +522,12 @@ desktop:
banner-crop-title: "Découpez la partie qui apparaitra comme bannière"
banner: "Bannière"
uploading-banner: "Téléversement d'une nouvelle bannière"
banner-updated: "La bannière est mise à jour"
banner-updated: "Mise à jour de la bannière avec succès"
choose-banner: "Choisir une bannière"
avatar-crop-title: "Découpez la partie qui apparaitra comme avatar"
avatar: "Avatar"
uploading-avatar: "Téléversement du nouvel avatar"
avatar-updated: "L'avatar est mis à jour"
avatar-updated: "Mise à jour de lavatar avec succès"
choose-avatar: "Choisir un avatar"
invalid-filetype: "Ce format de fichier nest pas pris en charge"
desktop/views/components/activity.chart.vue:
@@ -532,9 +539,9 @@ desktop/views/components/activity.vue:
title: "Activité"
toggle: "Afficher les vues"
desktop/views/components/calendar.vue:
title: "{year} / {month}"
prev: "Mois dernier"
next: "Mois prochain"
title: "{month} / {year}"
prev: "Mois précédent"
next: "Mois suivant"
go: "Cliquez pour naviguer"
desktop/views/components/choose-file-from-drive-window.vue:
chosen-files: "{count} fichier·s sélectionné·s"
@@ -560,7 +567,7 @@ desktop/views/components/drive.file.vue:
rename: "Renommer"
mark-as-sensitive: "Marquer comme sensible"
unmark-as-sensitive: "Ne pas marquer comme sensible"
copy-url: "Copier l'URL"
copy-url: "Copier lURL"
download: "Télécharger"
else-files: "Autres..."
set-as-avatar: "Utiliser en tant qu'avatar"
@@ -615,7 +622,7 @@ desktop/views/components/following-window.vue:
desktop/views/components/following.vue:
empty: "Vous ne suivez aucun compte."
desktop/views/components/friends-maker.vue:
title: "Utilisateurs recommandés :"
title: "Utilisateurs·rices recommandé·e·s :"
empty: "Impossible de trouver des utilisateurs·trices à recommander."
fetching: "Chargement"
refresh: "Plus"
@@ -666,7 +673,7 @@ desktop/views/components/post-form.vue:
replied: "Répondu !"
reposted: "Reposté !"
note-failed: "La note à échoué"
reply-failed: "La réponse à échoué"
reply-failed: "La réponse a échoué"
renote-failed: "Échec lors de la republication"
posting: "Publication …"
attach-media-from-local: "Joindre un média depuis votre appareil"
@@ -674,8 +681,9 @@ desktop/views/components/post-form.vue:
attach-cancel: "Annuler le fichier attaché"
insert-a-kao: "v('ω')v"
create-poll: "Créer un sondage"
text-remain: "{} charactères restants"
text-remain: "{} caractères restants"
recent-tags: "Récent"
local-only-message: "Ce message sera publié uniquement sur le fil local"
click-to-tagging: "Cliquer pour tagguer"
visibility: "Visibilité"
geolocation-alert: "Votre appareil ne prend pas en charge les services de localisation"
@@ -693,6 +701,7 @@ desktop/views/components/renote-form.vue:
quote: "Citer..."
cancel: "Annuler"
renote: "Republier"
renote-home: "Renote (Home)"
reposting: "Republication en cours …"
success: "Republié !"
failure: "La renote a échoué"
@@ -707,6 +716,7 @@ desktop/views/components/settings.vue:
profile: "Profil"
notification: "Notification"
apps: "Applications"
tags: "Hashtags"
mute-and-block: "Silencé·e·s / Bloqué·e·s"
blocking: "En cours de blocage"
security: "Sécurité"
@@ -714,7 +724,7 @@ desktop/views/components/settings.vue:
password: "Mot de Passe"
2fa: "Vérification en deux étapes"
other: "Autres"
license: "License"
license: "Licence"
theme: "Thèmes"
behaviour: "Comportement"
fetch-on-scroll: "Chargement lors du défilement"
@@ -749,6 +759,7 @@ desktop/views/components/settings.vue:
show-renoted-my-notes: "Afficher mes republications dans les fils"
show-local-renotes: "Afficher les partages locaux sur les fils"
show-maps: "Afficher la carte"
remain-deleted-note: "削除された投稿を表示し続ける"
deck-column-align: "Alignement des colonnes du Deck"
deck-column-align-center: "Centrer"
deck-column-align-left: "À gauche"
@@ -769,19 +780,19 @@ desktop/views/components/settings.vue:
cache-cleared: "Cache nettoyé"
cache-cleared-desc: "Veuillez recharger la page."
auto-watch: "Montre automatique"
auto-watch-desc: "リアクションしたり返信したりした投稿に関する通知を自動的に受け取るようにします。"
auto-watch-desc: "Recevez automatiquement les notifications de publications, réponses et réactions."
about: "À propose de Misskey"
operator: "L'admin de cette instance"
update: "Mise à jour de Misskey"
version: "Version :"
latest-version: "Dernière version :"
update-checking: "Recherche de mises à jour"
update-checking: "Vérification des mises à jour en cours …"
do-update: "Rechercher des mises à jour"
update-settings: "Paramètres avancés"
prevent-update: "Reporter les mises à jour (non recommandé)"
prevent-update-desc: "この設定をオンにしてもアップデートが反映される場合があります。この設定はこのデバイスのみ有効です。"
no-updates: "Aucune mise à jour disponible"
no-updates-desc: "Votre Misskey est à jour."
no-updates-desc: "Votre client Misskey est à jour."
update-available: "Nouvelle version disponible !"
update-available-desc: "Les mises à jour seront appliquées une fois la page est rechargée."
advanced-settings: "Réglages avancés"
@@ -800,23 +811,23 @@ desktop/views/components/settings.2fa.vue:
intro: "Si vous configurez la vérication en deux étapes vous aurez non seulement besoin de votre mot de passe mais aussi un appareil déjà pré-enregistré(tel que votre smartphone) ce qui ameliora grandement la sécurité de votre compte."
detail: "Voir les détails..."
url: "https://www.google.com/landing/2step/"
caution: "Activer la vérification en deux étapes vient aussi avec des contraintes, si vous perdez votre appareil ou ne pouvez tout simplement plus y accèder vous ne serez plus en mesure de vous connecter à Misskey."
caution: "Activer la vérification en deux étapes vient aussi avec des contraintes, si vous perdez votre appareil ou ne pouvez tout simplement plus y accéder vous ne serez plus en mesure de vous connecter à Misskey."
register: "Enregistrer un appareil"
already-registered: "Cette étape à déjà été complétée"
unregister: "Désactiver"
unregistered: "La vérication en deux étapes a été desactivée"
unregistered: "L'authentification à deux facteurs a été désactivée."
enter-password: "Entrez un mot de passe"
authenticator: "Tout d'abord vous devez installer Google Authenticator sur votre appareil"
authenticator: "Vous devez au préalable installer Google Authenticator sur votre appareil:"
howtoinstall: "Comment installer"
scan: "Ensuite scannez le QR code afficher sur votre écran:"
done: "Veuillez entrer le token qui s'affiche sur votre appareil:"
submit: "Envoyer"
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."
success: "Sauvegarde des paramètres avec succès !"
failed: "Lopération a échoué. Veuillez vous assurer que le jeton a été saisi correctement."
info: "À partir de maintenant, à chaque fois que vous vous connectez entrez votre mot de passe ainsi que le jeton généré sur votre appareil."
common/views/components/api-settings.vue:
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
caution: "Merci de ne pas introduire ce jeton dans aucune application ou le divulguer à quiconque. Ceci risque de compromettre votre compte."
regeneration-of-token: "Si votre jeton est compromis, vous pouvez le régénérer."
regenerate-token: "Régénérer le jeton"
token: "Jeton :"
@@ -825,7 +836,7 @@ common/views/components/api-settings.vue:
title: 'Console API'
endpoint: 'Point de terminaison'
parameter: 'Paramètres'
credential-info: "「i」パラメータは自動で付与されます。"
credential-info: "Le paramètre \"i\" est requis dans la console."
send: 'Envoyer'
sending: 'Envoi en cours'
response: 'Résultat'
@@ -836,7 +847,7 @@ common/views/components/drive-settings.vue:
in-use: "utilisé"
stats: "Statistiques"
common/views/components/mute-and-block.vue:
mute-and-block: "Silencer / Bloquer"
mute-and-block: "Silencés / Bloqués"
mute: "Mettre en sourdine"
block: "En cours blocage"
no-muted-users: "Aucun utilisateur·rice nest mis·e en sourdine"
@@ -913,15 +924,15 @@ desktop/views/components/users-list.vue:
desktop/views/components/users-list-item.vue:
followed: "vous suit"
desktop/views/components/window.vue:
popout: "ポップアウト"
popout: "Fenêtre contextuelle"
close: "Fermer"
admin/views/index.vue:
dashboard: "Tableau de bord"
instance: "Instance"
emoji: "Emoji"
moderators: "モデレーター"
emoji: "Émoji"
moderators: "Modérateurs"
users: "Utilisateur·rice·s"
update: "Mise à jour"
federation: "Fédération"
announcements: "Annonces"
hashtags: "Hashtags"
back-to-misskey: "Retour vers Misskey"
@@ -964,20 +975,20 @@ admin/views/instance.vue:
github-integration-info: "LURL callback est définit sur /api/gh/cb"
enable-github-integration: "Activer lauthentification avec Github"
github-integration-client-id: "ID client"
github-integration-client-secret: "Client Secret"
discord-integration-config: "Discord連携の設定"
discord-integration-info: "コールバックURLは /api/dc/cb に設定します。"
enable-discord-integration: "Discord連携を有効にする"
discord-integration-client-id: "Client ID"
discord-integration-client-secret: "Client Secret"
github-integration-client-secret: "Secret client"
discord-integration-config: "Paramètres dauthentification Discord"
discord-integration-info: "LURL callback est définit sur /api/dc/cb"
enable-discord-integration: "Activer lauthentification avec Discord"
discord-integration-client-id: "ID client"
discord-integration-client-secret: "Secret client"
proxy-account-config: "Compte proxy"
proxy-account-info: "プロキシアカウントは、特定の条件下でユーザーのリモートフォローを代行するアカウントです。例えば、ユーザーがリモートユーザーをリストに入れたとき、リストに入れられたユーザーを誰もフォローしていないとアクティビティがサーバーに配達されないため、代わりにプロキシアカウントがフォローするようにします。"
proxy-account-username: "Nom dutilisateur du compte proxy"
proxy-account-username-desc: "Spécifiez le nom dutilisateur du compte utilisé comme proxy."
proxy-account-warn: "Avant dentammer cette action, vous devez au préalable avoir créé un compte avec ce nom dutilisateur."
proxy-account-warn: "Avant dentamer cette action, vous devez au préalable avoir créé un compte avec ce nom dutilisateur."
max-note-text-length: "Nombre maximal de caractères pour les messages"
disable-registration: "Désactiver les inscriptions"
disable-local-timeline: "Désactiver lheure locale"
disable-local-timeline: "Désactiver le fil local"
invite: "Inviter"
save: "Sauvegarder"
saved: "Enregistré"
@@ -993,9 +1004,9 @@ admin/views/charts.vue:
charts:
federation-instances: "Nombre dinstances : augmentation/diminution"
federation-instances-total: "Nombre total dinstances"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes: "Nombre de publications : augmentation/diminution (combinés)"
local-notes: "Nombre des publications : augmentation/diminution (Local)"
remote-notes: "Nombre de publications : augmentation/diminution (distants)"
notes-total: "Total des publications"
users: "Nombre dutilisateur·rice·s : augmentation/diminution"
users-total: "Nombre total des utilisateur·rice·s"
@@ -1021,9 +1032,9 @@ admin/views/users.vue:
unverified: "Ce compte n'est plus vérifié"
admin/views/moderators.vue:
add-moderator:
title: "モデレーターの登録"
add: "登録"
added: "モデレーターを登録しました"
title: "Ajout dun modérateur"
add: "Ajouter"
added: "Ajouté en tant que modérateur"
admin/views/emoji.vue:
add-emoji:
title: "Ajouter un émoji"
@@ -1088,7 +1099,7 @@ desktop/views/pages/share.vue:
desktop/views/pages/tag.vue:
no-posts-found: "Aucune publication contenant « {q} » na été trouvée."
desktop/views/pages/user-list.users.vue:
users: "Utilisateurs"
users: "Utilisateurs·rices"
add-user: "Ajouter un utilisateur"
username: "Nom d'utilisateur"
desktop/views/pages/user/user.followers-you-know.vue:
@@ -1098,7 +1109,7 @@ desktop/views/pages/user/user.followers-you-know.vue:
desktop/views/pages/user/user.friends.vue:
title: "Mentions fréquentes"
loading: "Chargement en cours"
no-users: "Pas d'utilisateurs"
no-users: "Aucune mention fréquente"
desktop/views/pages/user/user.photos.vue:
title: "Photos"
loading: "Chargement en cours"
@@ -1122,9 +1133,9 @@ desktop/views/pages/user/user.header.vue:
followers: "Abonné·e·s"
is-bot: "Ce compte est un Bot"
years-old: "{age} ans"
year: "Année"
year: "/"
month: "/"
day: "-"
day: "/"
desktop/views/pages/user/user.timeline.vue:
default: "Publications"
with-replies: "Publications et réponses"
@@ -1150,14 +1161,14 @@ desktop/views/widgets/trends.vue:
refresh: "Afficher d'autres"
nothing: "Rien"
desktop/views/widgets/users.vue:
title: "Utilisateurs"
title: "Utilisateurs·rices"
refresh: "Afficher d'autres"
no-one: "Personne"
mobile/views/components/drive.vue:
used: "utilisé"
folder-count: "Dossier(s)"
folder-count: "Dossier·s"
count-separator: ", "
file-count: "Fichiers(s)"
file-count: "Fichier·s"
nothing-in-drive: "Rien"
folder-is-empty: "Ce dossier est vide"
prompt: "Que veux-tu faire ? (Entrez un nombre): <1 → Télécharger le fichier | 2 → Télécharger le fichier avec l'URL | 3 → Créer le dossier | 4 → Modifier le nom du dossier | 5 → Déplacer ce dossier | 6 → Supprimer ce dossier >"
@@ -1166,7 +1177,7 @@ mobile/views/components/drive.vue:
root-rename-alert: "L'emplacement actuel est la racine, pas le dossier, vous ne pouvez donc pas le renommer. Veuillez vous déplacer dans le dossier dont vous souhaitez modifier le nom."
root-move-alert: "L'emplacement actuel est la racine, ce n'est pas un dossier et il ne peut pas être déplacé. Veuillez vous déplacer dans le dossier que vous souhaitez déplacer."
url-prompt: "URL du fichier que vous souhaitez téléverser"
uploading: "アップロードをリクエストしました。アップロードが完了するまで時間がかかる場合があります。"
uploading: "Envoi demandé. Le téléversement pourrait prendre un certain temps avant de s'achever."
mobile/views/components/drive-file-chooser.vue:
select-file: "Choisissez un fichier"
mobile/views/components/drive-folder-chooser.vue:
@@ -1195,7 +1206,7 @@ common/views/components/follow-button.vue:
follow-processing: "En cours dabonnement"
follow-request: "Demande dabonnement"
mobile/views/components/friends-maker.vue:
title: "Abonnez-vous aux utilisateurs"
title: "Abonnez-vous à"
empty: "Impossible de trouver des utilisateurs·trices à recommander."
fetching: "Chargement"
refresh: "Voir plus"
@@ -1255,7 +1266,7 @@ mobile/views/components/ui.nav.vue:
darkmode: "Mode nuit"
settings: "Réglages"
admin: "Admin"
about: "À propose de Misskey"
about: "À propos de Misskey"
mobile/views/components/user-timeline.vue:
no-notes: "Cette utilisateur semble n'avoir rien poster pour le moment"
no-notes-with-media: "Aucune notes avec des médias"
@@ -1299,7 +1310,7 @@ mobile/views/pages/received-follow-requests.vue:
reject: "Refuser"
mobile/views/pages/note.vue:
title: "Post"
prev: "Note précedante"
prev: "Note précédente"
next: "Note suivante"
mobile/views/pages/notifications.vue:
notifications: "Notifications"
@@ -1317,7 +1328,7 @@ mobile/views/pages/settings.vue:
lang-tip: "Le rechargement de la page est requis afin d'appliquer les modifications."
recommended: "Recommandé"
auto: "Automatique"
specify-language: "Spécifier la langue"
specify-language: "Sélectionnez votre langue"
design: "Affichage et design"
dark-mode: "Mode nuit"
i-am-under-limited-internet: "J'ai un accès Internet limité"
@@ -1325,7 +1336,7 @@ mobile/views/pages/settings.vue:
contrasted-acct: "Nom dutilisateur contrasté"
timeline: "Fil d'actualité"
show-reply-target: "Afficher les réponses"
show-my-renotes: "Afficher mes republications"
show-my-renotes: "Afficher mes partages"
show-renoted-my-notes: "Afficher mes publications partagées"
show-local-renotes: "Afficher les publications partagées localement"
post-style: "Style de la publication"
@@ -1351,10 +1362,10 @@ mobile/views/pages/settings.vue:
github-connect: "Se connecter à votre compte GitHub"
github-reconnect: "Reconnecter"
github-disconnect: "Déconnecter"
discord: "Discord連携"
discord-connect: "Discordアカウントに接続する"
discord-reconnect: "再接続する"
discord-disconnect: "切断する"
discord: "Intégration avec Discord"
discord-connect: "Connecter votre compte Discord"
discord-reconnect: "Reconnecter"
discord-disconnect: "Déconnecter"
update: "Mise à jour de Misskey"
version: "Version :"
latest-version: "Dernière version :"
@@ -1377,7 +1388,7 @@ mobile/views/pages/user.vue:
notes: "Notes"
overview: "Aperçu"
timeline: "Fil d'actualité"
media: "Media"
media: "Média"
is-suspended: "This account has been suspended."
mute: "Mettre en sourdine"
unmute: "Enlever la sourdine"
@@ -1390,13 +1401,13 @@ mobile/views/pages/user/home.vue:
activity: "Activité"
keywords: "Mot clés"
domains: "Domaines"
frequently-replied-users: "Utilisateurs qui interagissent souvent"
frequently-replied-users: "Utilisateurs·rices mentionné·e·s souvent"
followers-you-know: "Abonné·e·s que vous connaissez"
last-used-at: "Dernière connexion il y a"
mobile/views/pages/user/home.followers-you-know.vue:
no-users: "Aucun utilisateur·rice connu·e"
mobile/views/pages/user/home.friends.vue:
no-users: "Pass d'utilisateurs"
no-users: "Aucun utilisateur·rice connu·e"
mobile/views/pages/user/home.notes.vue:
no-notes: "Pas de notes"
mobile/views/pages/user/home.photos.vue:

View File

@@ -5,7 +5,7 @@
const fs = require('fs');
const yaml = require('js-yaml');
const langs = ['de-DE', 'en-US', 'fr-FR', 'ja-JP', 'ja-KS', 'pl-PL', 'es-ES', 'nl-NL'];
const langs = ['de-DE', 'en-US', 'fr-FR', 'ja-JP', 'ja-KS', 'pl-PL', 'es-ES', 'nl-NL', 'zh-CN'];
const loadLocale = lang => yaml.safeLoad(fs.readFileSync(`${__dirname}/${lang}.yml`, 'utf-8'));
const locales = langs.map(lang => ({ [lang]: loadLocale(lang) }));

View File

@@ -1,10 +1,10 @@
---
meta:
lang: "日本語"
lang: "In Italiano"
divider: ""
common:
misskey: "A ⭐ of fediverse"
about-title: "A ⭐ of fediverse."
misskey: "A ⭐ of the fediverse"
about-title: "A ⭐ of the fediverse."
about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。"
intro:
title: "Misskeyって"
@@ -90,6 +90,9 @@ common:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
note-placeholders:
a: "今どうしてる?"
b: "何かありましたか?"
@@ -427,6 +430,10 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-public-desc: "リモートへは公開しない"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
@@ -676,6 +683,7 @@ desktop/views/components/post-form.vue:
create-poll: "アンケートを作成"
text-remain: "残り{}文字"
recent-tags: "最近"
local-only-message: "この投稿はローカルにのみ公開されます"
click-to-tagging: "クリックでタグ付け"
visibility: "公開範囲"
geolocation-alert: "お使いの端末は位置情報に対応していません"
@@ -693,6 +701,7 @@ desktop/views/components/renote-form.vue:
quote: "引用する..."
cancel: "キャンセル"
renote: "Renote"
renote-home: "Renote (Home)"
reposting: "しています..."
success: "Renoteしました"
failure: "Renoteに失敗しました"
@@ -707,6 +716,7 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "通知"
apps: "アプリ"
tags: "ハッシュタグ"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
@@ -749,6 +759,7 @@ desktop/views/components/settings.vue:
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
remain-deleted-note: "削除された投稿を表示し続ける"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
@@ -921,7 +932,7 @@ admin/views/index.vue:
emoji: "カスタム絵文字"
moderators: "モデレーター"
users: "ユーザー"
update: "更新"
federation: "連合"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
back-to-misskey: "Misskeyに戻る"

View File

@@ -96,6 +96,9 @@ common:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
note-placeholders:
a: "今どうしてる?"
@@ -471,6 +474,10 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-public-desc: "リモートへは公開しない"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
common/views/components/trends.vue:
count: "{}人が投稿"
@@ -761,6 +768,7 @@ desktop/views/components/post-form.vue:
create-poll: "アンケートを作成"
text-remain: "残り{}文字"
recent-tags: "最近"
local-only-message: "この投稿はローカルにのみ公開されます"
click-to-tagging: "クリックでタグ付け"
visibility: "公開範囲"
geolocation-alert: "お使いの端末は位置情報に対応していません"
@@ -781,6 +789,7 @@ desktop/views/components/renote-form.vue:
quote: "引用する..."
cancel: "キャンセル"
renote: "Renote"
renote-home: "Renote (Home)"
reposting: "しています..."
success: "Renoteしました"
failure: "Renoteに失敗しました"
@@ -799,6 +808,7 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "通知"
apps: "アプリ"
tags: "ハッシュタグ"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
@@ -843,6 +853,7 @@ desktop/views/components/settings.vue:
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
remain-deleted-note: "削除された投稿を表示し続ける"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
@@ -1045,7 +1056,7 @@ admin/views/index.vue:
emoji: "カスタム絵文字"
moderators: "モデレーター"
users: "ユーザー"
update: "更新"
federation: "連合"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
back-to-misskey: "Misskeyに戻る"

View File

@@ -90,6 +90,9 @@ common:
specified: "ダイレクト"
specified-desc: "今から言うユーザー以外に見せんとってや"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
note-placeholders:
a: "今なにしてん?"
b: "何かあったんか?"
@@ -427,6 +430,10 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト"
specified-desc: "今から言うユーザー以外に見せんとってや"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-public-desc: "リモートへは公開しない"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "流行は自分で作るんや"
@@ -676,6 +683,7 @@ desktop/views/components/post-form.vue:
create-poll: "アンケートを作成"
text-remain: "残り{}文字"
recent-tags: "最近のタグ"
local-only-message: "この投稿はローカルにのみ公開されます"
click-to-tagging: "クリックでタグ付け"
visibility: "公開範囲"
geolocation-alert: "あんさんのつことる端末は位置情報に対応しとらんみたいやわ、知らんけど。"
@@ -693,6 +701,7 @@ desktop/views/components/renote-form.vue:
quote: "取ってくる……"
cancel: "やめとくわ"
renote: "Renote"
renote-home: "Renote (Home)"
reposting: "やっとります..."
success: "Renoteしたで"
failure: "Renoteでけへん"
@@ -707,6 +716,7 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "通知"
apps: "アプリ"
tags: "ハッシュタグ"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
@@ -749,6 +759,7 @@ desktop/views/components/settings.vue:
show-renoted-my-notes: "わしのRenoteもタイムライン載せてくれや"
show-local-renotes: "ローカル投稿のRenoteも見たいんや"
show-maps: "地図勝手にバァーって開いてくれ"
remain-deleted-note: "削除された投稿を表示し続ける"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "真ん中"
deck-column-align-left: "左"
@@ -921,7 +932,7 @@ admin/views/index.vue:
emoji: "カスタム絵文字"
moderators: "モデレーター"
users: "ユーザー"
update: "更新"
federation: "連合"
announcements: "知っといてや"
hashtags: "ハッシュタグ"
back-to-misskey: "Misskeyに戻る"

View File

@@ -90,6 +90,9 @@ common:
specified: "다이렉트"
specified-desc: "지정한 사용자에게만 공개"
private: "비공개"
local-public: "公開 (ローカルのみ)"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
note-placeholders:
a: "지금 어떻게하고있어?"
b: "뭔가 있었습니까?"
@@ -427,6 +430,10 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-public-desc: "リモートへは公開しない"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
@@ -676,6 +683,7 @@ desktop/views/components/post-form.vue:
create-poll: "アンケートを作成"
text-remain: "残り{}文字"
recent-tags: "最近"
local-only-message: "この投稿はローカルにのみ公開されます"
click-to-tagging: "クリックでタグ付け"
visibility: "公開範囲"
geolocation-alert: "お使いの端末は位置情報に対応していません"
@@ -693,6 +701,7 @@ desktop/views/components/renote-form.vue:
quote: "引用する..."
cancel: "キャンセル"
renote: "Renote"
renote-home: "Renote (Home)"
reposting: "しています..."
success: "Renoteしました"
failure: "Renoteに失敗しました"
@@ -707,6 +716,7 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "通知"
apps: "アプリ"
tags: "ハッシュタグ"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
@@ -749,6 +759,7 @@ desktop/views/components/settings.vue:
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
remain-deleted-note: "削除された投稿を表示し続ける"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
@@ -921,7 +932,7 @@ admin/views/index.vue:
emoji: "カスタム絵文字"
moderators: "モデレーター"
users: "ユーザー"
update: "更新"
federation: "連合"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
back-to-misskey: "Misskeyに戻る"

View File

@@ -90,6 +90,9 @@ common:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
note-placeholders:
a: "今どうしてる?"
b: "何かありましたか?"
@@ -427,6 +430,10 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-public-desc: "リモートへは公開しない"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
@@ -676,6 +683,7 @@ desktop/views/components/post-form.vue:
create-poll: "Peiling creëren"
text-remain: "{} resterende tekens"
recent-tags: "最近"
local-only-message: "この投稿はローカルにのみ公開されます"
click-to-tagging: "クリックでタグ付け"
visibility: "公開範囲"
geolocation-alert: "お使いの端末は位置情報に対応していません"
@@ -693,6 +701,7 @@ desktop/views/components/renote-form.vue:
quote: "Citeren..."
cancel: "Annuleren"
renote: "Renote"
renote-home: "Renote (Home)"
reposting: "Bezig met herplaatsen..."
success: "Hergeplaatst!"
failure: "Renote mislukt"
@@ -707,6 +716,7 @@ desktop/views/components/settings.vue:
profile: "Profiel"
notification: "Melding"
apps: "Apps"
tags: "ハッシュタグ"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "Beveiliging"
@@ -749,6 +759,7 @@ desktop/views/components/settings.vue:
show-renoted-my-notes: "Mijn gerenote bericht tonen op de tijdlijn"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Kaart tonen"
remain-deleted-note: "削除された投稿を表示し続ける"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
@@ -921,7 +932,7 @@ admin/views/index.vue:
emoji: "カスタム絵文字"
moderators: "モデレーター"
users: "ユーザー"
update: "更新"
federation: "連合"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
back-to-misskey: "Misskeyに戻る"

View File

@@ -1,6 +1,6 @@
---
meta:
lang: "norsk"
lang: "Norsk Bokmål"
divider: ""
common:
misskey: "En ⭐ av fediverse"
@@ -90,6 +90,9 @@ common:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "Privat"
local-public: "公開 (ローカルのみ)"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
note-placeholders:
a: "今どうしてる?"
b: "何かありましたか?"
@@ -427,6 +430,10 @@ common/views/components/visibility-chooser.vue:
specified: "Direkte"
specified-desc: "指定したユーザーにのみ公開"
private: "Privat"
local-public: "公開 (ローカルのみ)"
local-public-desc: "リモートへは公開しない"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
@@ -676,6 +683,7 @@ desktop/views/components/post-form.vue:
create-poll: "アンケートを作成"
text-remain: "残り{}文字"
recent-tags: "Nylig"
local-only-message: "この投稿はローカルにのみ公開されます"
click-to-tagging: "クリックでタグ付け"
visibility: "Synlighet"
geolocation-alert: "お使いの端末は位置情報に対応していません"
@@ -693,6 +701,7 @@ desktop/views/components/renote-form.vue:
quote: "引用する..."
cancel: "Avbryt"
renote: "Renote"
renote-home: "Renote (Home)"
reposting: "しています..."
success: "Renoteしました"
failure: "Renoteに失敗しました"
@@ -707,6 +716,7 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "Notifikasjon"
apps: "Apper"
tags: "ハッシュタグ"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
@@ -749,6 +759,7 @@ desktop/views/components/settings.vue:
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
remain-deleted-note: "削除された投稿を表示し続ける"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
@@ -921,7 +932,7 @@ admin/views/index.vue:
emoji: "カスタム絵文字"
moderators: "モデレーター"
users: "ユーザー"
update: "更新"
federation: "連合"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
back-to-misskey: "Misskeyに戻る"

View File

@@ -90,6 +90,9 @@ common:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
note-placeholders:
a: "Co robisz?"
b: "Co się wydarzyło?"
@@ -427,6 +430,10 @@ common/views/components/visibility-chooser.vue:
specified: "Bezpośredni"
specified-desc: "Tylko dla określonych użytkowników"
private: "Prywatny"
local-public: "公開 (ローカルのみ)"
local-public-desc: "リモートへは公開しない"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
@@ -676,6 +683,7 @@ desktop/views/components/post-form.vue:
create-poll: "Utwórz ankietę"
text-remain: "pozostałe znaki: {}"
recent-tags: "Ostatnie"
local-only-message: "この投稿はローカルにのみ公開されます"
click-to-tagging: "Naciśnij aby oznaczyć"
visibility: "Widoczność"
geolocation-alert: "Twoje urządzenie nie obsługuje geolokalizacji."
@@ -693,6 +701,7 @@ desktop/views/components/renote-form.vue:
quote: "Cytuj…"
cancel: "Anuluj"
renote: "Udostępnij"
renote-home: "Renote (Home)"
reposting: "Udostępnianie…"
success: "Udostępniono!"
failure: "Nie udało się udostępnić"
@@ -707,6 +716,7 @@ desktop/views/components/settings.vue:
profile: "Profil"
notification: "Powiadomienia"
apps: "Aplikacje"
tags: "ハッシュタグ"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "Bezpieczeństwo"
@@ -749,6 +759,7 @@ desktop/views/components/settings.vue:
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Automatycznie pokazuj mapę"
remain-deleted-note: "削除された投稿を表示し続ける"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
@@ -921,7 +932,7 @@ admin/views/index.vue:
emoji: "カスタム絵文字"
moderators: "モデレーター"
users: "ユーザー"
update: "更新"
federation: "連合"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
back-to-misskey: "Misskeyに戻る"

View File

@@ -90,6 +90,9 @@ common:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
note-placeholders:
a: "O que está fazendo?"
b: "O que está acontecendo?"
@@ -427,6 +430,10 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-public-desc: "リモートへは公開しない"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
@@ -676,6 +683,7 @@ desktop/views/components/post-form.vue:
create-poll: "アンケートを作成"
text-remain: "残り{}文字"
recent-tags: "最近"
local-only-message: "この投稿はローカルにのみ公開されます"
click-to-tagging: "クリックでタグ付け"
visibility: "公開範囲"
geolocation-alert: "お使いの端末は位置情報に対応していません"
@@ -693,6 +701,7 @@ desktop/views/components/renote-form.vue:
quote: "引用する..."
cancel: "キャンセル"
renote: "Renote"
renote-home: "Renote (Home)"
reposting: "しています..."
success: "Renoteしました"
failure: "Renoteに失敗しました"
@@ -707,6 +716,7 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "通知"
apps: "アプリ"
tags: "ハッシュタグ"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
@@ -749,6 +759,7 @@ desktop/views/components/settings.vue:
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
remain-deleted-note: "削除された投稿を表示し続ける"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
@@ -921,7 +932,7 @@ admin/views/index.vue:
emoji: "カスタム絵文字"
moderators: "モデレーター"
users: "ユーザー"
update: "更新"
federation: "連合"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
back-to-misskey: "Misskeyに戻る"

View File

@@ -90,6 +90,9 @@ common:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
note-placeholders:
a: "今どうしてる?"
b: "何かありましたか?"
@@ -427,6 +430,10 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
local-public: "公開 (ローカルのみ)"
local-public-desc: "リモートへは公開しない"
local-home: "ホーム (ローカルのみ)"
local-followers: "フォロワー (ローカルのみ)"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
@@ -676,6 +683,7 @@ desktop/views/components/post-form.vue:
create-poll: "アンケートを作成"
text-remain: "残り{}文字"
recent-tags: "最近"
local-only-message: "この投稿はローカルにのみ公開されます"
click-to-tagging: "クリックでタグ付け"
visibility: "公開範囲"
geolocation-alert: "お使いの端末は位置情報に対応していません"
@@ -693,6 +701,7 @@ desktop/views/components/renote-form.vue:
quote: "引用する..."
cancel: "キャンセル"
renote: "Renote"
renote-home: "Renote (Home)"
reposting: "しています..."
success: "Renoteしました"
failure: "Renoteに失敗しました"
@@ -707,6 +716,7 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "通知"
apps: "アプリ"
tags: "ハッシュタグ"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
@@ -749,6 +759,7 @@ desktop/views/components/settings.vue:
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
remain-deleted-note: "削除された投稿を表示し続ける"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
@@ -921,7 +932,7 @@ admin/views/index.vue:
emoji: "カスタム絵文字"
moderators: "モデレーター"
users: "ユーザー"
update: "更新"
federation: "連合"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
back-to-misskey: "Misskeyに戻る"

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "10.52.0",
"clientVersion": "2.0.11848",
"version": "10.55.0",
"clientVersion": "2.0.11909",
"codename": "nighthike",
"main": "./built/index.js",
"private": true,
@@ -46,6 +46,7 @@
"@types/is-root": "1.0.0",
"@types/is-url": "1.2.28",
"@types/js-yaml": "3.11.2",
"@types/katex": "0.5.0",
"@types/koa": "2.0.46",
"@types/koa-bodyparser": "5.0.1",
"@types/koa-compress": "2.0.8",
@@ -80,7 +81,7 @@
"@types/tinycolor2": "1.4.1",
"@types/tmp": "0.0.33",
"@types/uuid": "3.4.4",
"@types/webpack": "4.4.18",
"@types/webpack": "4.4.19",
"@types/webpack-stream": "3.2.10",
"@types/websocket": "0.0.40",
"@types/ws": "6.0.1",
@@ -140,6 +141,7 @@
"jsdom": "13.0.0",
"json5": "2.1.0",
"json5-loader": "1.0.1",
"katex": "0.10.0",
"koa": "2.6.1",
"koa-bodyparser": "4.2.1",
"koa-compress": "3.0.0",
@@ -158,7 +160,7 @@
"mocha": "5.2.0",
"moji": "0.5.1",
"moment": "2.22.2",
"mongodb": "3.1.8",
"mongodb": "3.1.9",
"monk": "6.0.6",
"ms": "2.1.1",
"nan": "2.11.1",
@@ -189,7 +191,7 @@
"s-age": "1.1.2",
"seedrandom": "2.4.4",
"sharp": "0.21.0",
"showdown": "1.8.7",
"showdown": "1.9.0",
"showdown-highlightjs-extension": "0.1.2",
"speakeasy": "2.0.0",
"stringz": "1.0.0",
@@ -207,7 +209,7 @@
"ts-node": "7.0.1",
"tslint": "5.10.0",
"typescript": "3.1.6",
"typescript-eslint-parser": "20.1.1",
"typescript-eslint-parser": "21.0.0",
"uglify-es": "3.3.9",
"url-loader": "1.1.2",
"uuid": "3.3.2",
@@ -222,7 +224,7 @@
"vue-marquee-text-component": "1.1.0",
"vue-router": "3.0.1",
"vue-style-loader": "4.1.2",
"vue-svg-inline-loader": "1.2.1",
"vue-svg-inline-loader": "1.2.2",
"vue-template-compiler": "2.5.17",
"vuedraggable": "2.16.0",
"vuewordcloud": "18.7.11",

View File

@@ -8,13 +8,19 @@
<p>{{ $t('@.ai-chan-kawaii') }}</p>
</header>
<marquee-text v-if="instances.length > 0" class="instances" :repeat="10" :duration="60">
<span v-for="instance in instances" class="instance">
<b :style="{ background: instance.bg }">{{ instance.host }}</b>{{ instance.notesCount | number }} / {{ instance.usersCount | number }}
</span>
</marquee-text>
<div v-if="stats" class="stats">
<div>
<div>
<div><fa icon="user"/></div>
<div>
<span>{{ $t('accounts') }}</span>
<b class="primary">{{ stats.originalUsersCount | number }}</b>
<b>{{ stats.originalUsersCount | number }}</b>
</div>
</div>
<div>
@@ -27,7 +33,7 @@
<div><fa icon="pencil-alt"/></div>
<div>
<span>{{ $t('notes') }}</span>
<b class="primary">{{ stats.originalNotesCount | number }}</b>
<b>{{ stats.originalNotesCount | number }}</b>
</div>
</div>
<div>
@@ -84,6 +90,8 @@ import XCpuMemory from "./cpu-memory.vue";
import XCharts from "./charts.vue";
import XApLog from "./ap-log.vue";
import { faDatabase } from '@fortawesome/free-solid-svg-icons';
import MarqueeText from 'vue-marquee-text-component';
import randomColor from 'randomcolor';
export default Vue.extend({
i18n: i18n('admin/views/dashboard.vue'),
@@ -91,7 +99,8 @@ export default Vue.extend({
components: {
XCpuMemory,
XCharts,
XApLog
XApLog,
MarqueeText
},
data() {
@@ -99,6 +108,8 @@ export default Vue.extend({
stats: null,
connection: null,
meta: null,
instances: [],
clock: null,
faDatabase
};
},
@@ -106,22 +117,40 @@ export default Vue.extend({
created() {
this.connection = this.$root.stream.useSharedConnection('serverStats');
this.updateStats();
this.clock = setInterval(this.updateStats, 1000);
this.$root.getMeta().then(meta => {
this.meta = meta;
});
this.$root.api('stats').then(stats => {
this.stats = stats;
this.$root.api('instances', {
sort: '+notes'
}).then(instances => {
instances.forEach(i => {
i.bg = randomColor({
seed: i.host,
luminosity: 'dark'
});
});
this.instances = instances;
});
},
beforeDestroy() {
this.connection.dispose();
clearInterval(this.clock);
},
methods: {
setChartSrc(src) {
this.$refs.charts.setSrc(src);
},
updateStats() {
this.$root.api('stats', {}, false, true).then(stats => {
this.stats = stats;
});
}
}
});
@@ -136,7 +165,6 @@ export default Vue.extend({
> header
display flex
margin-bottom 16px
padding-bottom 16px
border-bottom solid 1px var(--adminDashboardHeaderBorder)
color var(--adminDashboardHeaderFg)
@@ -161,6 +189,20 @@ export default Vue.extend({
margin-left auto
margin-right 0
> .instances
padding 16px
color var(--adminDashboardHeaderFg)
font-size 13px
>>> .instance
margin 0 10px
> b
padding 2px 6px
margin-right 4px
border-radius 4px
color #fff
> .stats
display flex
justify-content space-between
@@ -201,9 +243,6 @@ export default Vue.extend({
> b
display block
&.primary
color var(--primary)
> div:last-child
display flex
padding 6px 16px

View File

@@ -22,12 +22,12 @@
<li @click="nav('instance')" :class="{ active: page == 'instance' }"><fa icon="cog" fixed-width/>{{ $t('instance') }}</li>
<li @click="nav('moderators')" :class="{ active: page == 'moderators' }"><fa :icon="faHeadset" fixed-width/>{{ $t('moderators') }}</li>
<li @click="nav('users')" :class="{ active: page == 'users' }"><fa icon="users" fixed-width/>{{ $t('users') }}</li>
<!-- <li @click="nav('federation')" :class="{ active: page == 'federation' }"><fa :icon="faShareAlt" fixed-width/>{{ $t('federation') }}</li> -->
<li @click="nav('emoji')" :class="{ active: page == 'emoji' }"><fa :icon="faGrin" fixed-width/>{{ $t('emoji') }}</li>
<li @click="nav('announcements')" :class="{ active: page == 'announcements' }"><fa icon="broadcast-tower" fixed-width/>{{ $t('announcements') }}</li>
<li @click="nav('hashtags')" :class="{ active: page == 'hashtags' }"><fa icon="hashtag" fixed-width/>{{ $t('hashtags') }}</li>
<!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }"><fa icon="cloud" fixed-width/>{{ $t('@.drive') }}</li> -->
<!-- <li @click="nav('update')" :class="{ active: page == 'update' }">{{ $t('update') }}</li> -->
</ul>
<div class="back-to-misskey">
<a href="/"><fa :icon="faArrowLeft"/> {{ $t('back-to-misskey') }}</a>
@@ -37,11 +37,6 @@
</div>
</nav>
<main>
<marquee-text v-if="instances.length > 0" class="instances" :repeat="10" :duration="30">
<span v-for="instance in instances" class="instance">
<b :style="{ background: instance.bg }">{{ instance.host }}</b>{{ instance.notesCount | number }} / {{ instance.usersCount | number }}
</span>
</marquee-text>
<div class="page">
<div v-if="page == 'dashboard'"><x-dashboard/></div>
<div v-if="page == 'instance'"><x-instance/></div>
@@ -68,10 +63,8 @@ import XEmoji from "./emoji.vue";
import XAnnouncements from "./announcements.vue";
import XHashtags from "./hashtags.vue";
import XUsers from "./users.vue";
import { faHeadset, faArrowLeft } from '@fortawesome/free-solid-svg-icons';
import { faHeadset, faArrowLeft, faShareAlt } from '@fortawesome/free-solid-svg-icons';
import { faGrin } from '@fortawesome/free-regular-svg-icons';
import MarqueeText from 'vue-marquee-text-component';
import randomColor from 'randomcolor';
// Detect the user agent
const ua = navigator.userAgent.toLowerCase();
@@ -86,8 +79,7 @@ export default Vue.extend({
XEmoji,
XAnnouncements,
XHashtags,
XUsers,
MarqueeText
XUsers
},
provide: {
isMobile
@@ -98,25 +90,12 @@ export default Vue.extend({
version,
isMobile,
navOpend: !isMobile,
instances: [],
faGrin,
faArrowLeft,
faHeadset
faHeadset,
faShareAlt
};
},
created() {
this.$root.api('instances', {
sort: '+notes'
}).then(instances => {
instances.forEach(i => {
i.bg = randomColor({
seed: i.host,
luminosity: 'dark'
});
});
this.instances = instances;
});
},
methods: {
nav(page: string) {
this.page = page;
@@ -287,22 +266,8 @@ export default Vue.extend({
width 100%
padding 0 0 0 250px
> .instances
padding 10px
background #000
color #fff
font-size 13px
>>> .instance
margin 0 10px
> b
padding 0px 6px
margin-right 4px
border-radius 4px
> .page
max-width 1300px
max-width 1150px
&.isMobile
> main

View File

@@ -69,11 +69,14 @@
//#endregion
let locale = localStorage.getItem('locale');
if (locale == null) {
const localeKey = localStorage.getItem('localeKey');
if (locale == null || localeKey != `${ver}.${lang}`) {
const locale = await fetch(`/assets/locales/${lang}.json?ver=${ver}`)
.then(response => response.json());
localStorage.setItem('locale', JSON.stringify(locale));
localStorage.setItem('localeKey', `${ver}.${lang}`);
}
// Detect the user agent

View File

@@ -1,5 +1,5 @@
import parse from '../../../../mfm/parse';
import { sum } from '../../../../prelude/array';
import { sum, unique } from '../../../../prelude/array';
import shouldMuteNote from './should-mute-note';
import MkNoteMenu from '../views/components/note-menu.vue';
import MkReactionPicker from '../views/components/reaction-picker.vue';
@@ -78,9 +78,9 @@ export default (opts: Opts = {}) => ({
urls(): string[] {
if (this.appearNote.text) {
const ast = parse(this.appearNote.text);
return ast
return unique(ast
.filter(t => (t.type == 'url' || t.type == 'link') && !t.silent)
.map(t => t.url);
.map(t => t.url));
} else {
return null;
}

View File

@@ -0,0 +1,26 @@
<template>
<span v-html="compiledFormula"></span>
</template>
<script lang="ts">
import Vue from 'vue';
import * as katex from 'katex';
export default Vue.extend({
props: {
formula: {
type: String,
required: true
}
},
computed: {
compiledFormula(): any {
return katex.renderToString(this.formula);
}
}
});
</script>
<style>
@import "../../../../../../node_modules/katex/dist/katex.min.css";
</style>

View File

@@ -0,0 +1,20 @@
<template>
<x-formula :formula="formula"/>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
components: {
XFormula: () => import('./formula-core.vue').then(m => m.default)
},
props: {
formula: {
type: String,
required: true
}
}
});
</script>

View File

@@ -34,6 +34,7 @@
import Vue from 'vue';
import i18n from '../../../i18n';
import parse from '../../../../../mfm/parse';
import { unique } from '../../../../../prelude/array';
export default Vue.extend({
i18n: i18n('common/views/components/messaging-room.message.vue'),
@@ -49,9 +50,9 @@ export default Vue.extend({
urls(): string[] {
if (this.message.text) {
const ast = parse(this.message.text);
return ast
return unique(ast
.filter(t => (t.type == 'url' || t.type == 'link') && !t.silent)
.map(t => t.url);
.map(t => t.url));
} else {
return null;
}

View File

@@ -3,8 +3,9 @@ import { length } from 'stringz';
import parse from '../../../../../mfm/parse';
import getAcct from '../../../../../misc/acct/render';
import MkUrl from './url.vue';
import MkGoogle from './google.vue';
import { concat } from '../../../../../prelude/array';
import MkFormula from './formula.vue';
import MkGoogle from './google.vue';
export default Vue.component('misskey-flavored-markdown', {
props: {
@@ -199,7 +200,17 @@ export default Vue.component('misskey-flavored-markdown', {
})];
}
case 'math': {
//const MkFormula = () => import('./formula.vue').then(m => m.default);
return [createElement(MkFormula, {
props: {
formula: token.formula
}
})];
}
case 'search': {
//const MkGoogle = () => import('./google.vue').then(m => m.default);
return [createElement(MkGoogle, {
props: {
q: token.query

View File

@@ -14,11 +14,12 @@
<mk-time :time="note.createdAt"/>
</router-link>
<span class="visibility" v-if="note.visibility != 'public'">
<template v-if="note.visibility == 'home'"><fa icon="home"/></template>
<template v-if="note.visibility == 'followers'"><fa icon="unlock"/></template>
<template v-if="note.visibility == 'specified'"><fa icon="envelope"/></template>
<template v-if="note.visibility == 'private'"><fa icon="lock"/></template>
<fa v-if="note.visibility == 'home'" icon="home"/>
<fa v-if="note.visibility == 'followers'" icon="unlock"/>
<fa v-if="note.visibility == 'specified'" icon="envelope"/>
<fa v-if="note.visibility == 'private'" icon="lock"/>
</span>
<span class="localOnly" v-if="note.localOnly == true"><fa icon="heart"/></span>
</div>
</header>
</template>
@@ -115,4 +116,7 @@ export default Vue.extend({
> .visibility
margin-left 8px
> .localOnly
margin-left 4px
</style>

View File

@@ -12,9 +12,9 @@
</ui-input>
<ui-input v-if="user && user.twoFactorEnabled" v-model="token" type="number" required styl="fill"/>
<ui-button type="submit" :disabled="signing">{{ signing ? $t('signing-in') : $t('signin') }}</ui-button>
<p style="margin: 8px 0;"><a :href="`${apiUrl}/signin/twitter`">{{ $t('signin-with-twitter') }}</a></p>
<p style="margin: 8px 0;"><a :href="`${apiUrl}/signin/github`">{{ $t('signin-with-github') }}</a></p>
<p style="margin: 8px 0;"><a :href="`${apiUrl}/signin/discord`">{{ $t('signin-with-discord') /* TODO: Make these layouts better */ }}</a></p>
<p v-if="meta && meta.enableTwitterIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/twitter`">{{ $t('signin-with-twitter') }}</a></p>
<p v-if="meta && meta.enableGithubIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/github`">{{ $t('signin-with-github') }}</a></p>
<p v-if="meta && meta.enableDiscordIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/discord`">{{ $t('signin-with-discord') /* TODO: Make these layouts better */ }}</a></p>
</form>
</template>
@@ -41,9 +41,15 @@ export default Vue.extend({
password: '',
token: '',
apiUrl,
host: toUnicode(host)
host: toUnicode(host),
meta: null
};
},
created() {
this.$root.getMeta().then(meta => {
this.meta = meta;
});
},
methods: {
onUsernameChange() {
this.$root.api('users/show', {

View File

@@ -53,8 +53,8 @@ export default Vue.extend({
ago >= 3600 ? this.$t('@.time.hours_ago') .replace('{}', (~~(ago / 3600)).toString()) :
ago >= 60 ? this.$t('@.time.minutes_ago').replace('{}', (~~(ago / 60)).toString()) :
ago >= 10 ? this.$t('@.time.seconds_ago').replace('{}', (~~(ago % 60)).toString()) :
ago >= 0 ? this.$t('@.time.just_now') :
ago < 0 ? this.$t('@.time.future') :
ago >= -1 ? this.$t('@.time.just_now') :
ago < -1 ? this.$t('@.time.future') :
this.$t('@.time.unknown'));
}
},

View File

@@ -35,6 +35,25 @@
<span>{{ $t('private') }}</span>
</div>
</div>
<div @click="choose('local-public')" :class="{ active: v == 'local-public' }">
<div><fa icon="globe"/></div>
<div>
<span>{{ $t('local-public') }}</span>
<span>{{ $t('local-public-desc') }}</span>
</div>
</div>
<div @click="choose('local-home')" :class="{ active: v == 'local-home' }">
<div><fa icon="home"/></div>
<div>
<span>{{ $t('local-home') }}</span>
</div>
</div>
<div @click="choose('local-followers')" :class="{ active: v == 'local-followers' }">
<div><fa icon="unlock"/></div>
<div>
<span>{{ $t('local-followers') }}</span>
</div>
</div>
</div>
</div>
</template>

View File

@@ -3,6 +3,7 @@
<p>Maintainer: <b><a :href="'mailto:' + meta.maintainer.email" target="_blank">{{ meta.maintainer.name }}</a></b></p>
<p>Machine: {{ meta.machine }}</p>
<p>Node: {{ meta.node }}</p>
<p>Version: {{ meta.version }} </p>
</div>
</template>

View File

@@ -94,7 +94,7 @@ import MkRenoteFormWindow from './renote-form-window.vue';
import MkNoteMenu from '../../../common/views/components/note-menu.vue';
import MkReactionPicker from '../../../common/views/components/reaction-picker.vue';
import XSub from './note.sub.vue';
import { sum } from '../../../../../prelude/array';
import { sum, unique } from '../../../../../prelude/array';
import noteSubscriber from '../../../common/scripts/note-subscriber';
export default Vue.extend({
@@ -149,9 +149,9 @@ export default Vue.extend({
urls(): string[] {
if (this.p.text) {
const ast = parse(this.p.text);
return ast
return unique(ast
.filter(t => (t.type == 'url' || t.type == 'link') && !t.silent)
.map(t => t.url);
.map(t => t.url));
} else {
return null;
}

View File

@@ -2,7 +2,7 @@
<div
class="note"
:class="{ mini }"
v-show="appearNote.deletedAt == null && !hideThisNote"
v-show="(this.$store.state.settings.remainDeletedNote || appearNote.deletedAt == null) && !hideThisNote"
:tabindex="appearNote.deletedAt == null ? '-1' : null"
v-hotkey="keymap"
:title="title"
@@ -20,12 +20,19 @@
<router-link class="name" :to="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</router-link>
<span>{{ this.$t('reposted-by').substr(this.$t('reposted-by').indexOf('}') + 1) }}</span>
<mk-time :time="note.createdAt"/>
<span class="visibility" v-if="note.visibility != 'public'">
<fa v-if="note.visibility == 'home'" icon="home"/>
<fa v-if="note.visibility == 'followers'" icon="unlock"/>
<fa v-if="note.visibility == 'specified'" icon="envelope"/>
<fa v-if="note.visibility == 'private'" icon="lock"/>
</span>
<span class="localOnly" v-if="note.localOnly == true"><fa icon="heart"/></span>
</div>
<article>
<mk-avatar class="avatar" :user="appearNote.user"/>
<div class="main">
<mk-note-header class="header" :note="appearNote" :mini="mini"/>
<div class="body">
<div class="body" v-if="appearNote.deletedAt == null">
<p v-if="appearNote.cw != null" class="cw">
<span class="text" v-if="appearNote.cw != ''">{{ appearNote.cw }}</span>
<mk-cw-button v-model="showContent"/>
@@ -46,7 +53,7 @@
<mk-url-preview v-for="url in urls" :url="url" :key="url" :mini="mini"/>
</div>
</div>
<footer>
<footer v-if="appearNote.deletedAt == null">
<span class="app" v-if="appearNote.app && mini && $store.state.settings.showVia">via <b>{{ appearNote.app.name }}</b></span>
<mk-reactions-viewer :note="appearNote" ref="reactionsViewer"/>
<button class="replyButton" @click="reply()" :title="$t('reply')">
@@ -64,6 +71,7 @@
<fa icon="ellipsis-h"/>
</button>
</footer>
<div class="deleted" v-if="appearNote.deletedAt != null">{{ $t('deleted') }}</div>
</div>
</article>
<div class="replies" v-if="detail && replies.length > 0">
@@ -82,6 +90,7 @@ import noteSubscriber from '../../../common/scripts/note-subscriber';
export default Vue.extend({
i18n: i18n('desktop/views/components/note.vue'),
components: {
XSub
},
@@ -199,9 +208,6 @@ export default Vue.extend({
> span
flex-shrink 0
&:last-of-type
margin-right 8px
.name
overflow hidden
flex-shrink 1
@@ -215,6 +221,18 @@ export default Vue.extend({
flex-shrink 0
font-size 0.9em
> .visibility
margin-left 8px
[data-icon]
margin-right 0
> .localOnly
margin-left 4px
[data-icon]
margin-right 0
& + article
padding-top 8px
@@ -327,6 +345,7 @@ export default Vue.extend({
margin-left 0.5em
color var(--noteHeaderInfo)
font-size 0.8em
> button
margin 0 28px 0 0
padding 0 8px
@@ -360,6 +379,10 @@ export default Vue.extend({
&.reacted, &.reacted:hover
color var(--noteActionsReactionHover)
> .deleted
color var(--noteText)
opacity 0.7
</style>
<style lang="stylus" module>

View File

@@ -14,6 +14,7 @@
<b>{{ $t('recent-tags') }}:</b>
<a v-for="tag in recentHashtags.slice(0, 5)" @click="addTag(tag)" :title="$t('click-to-tagging')">#{{ tag }}</a>
</div>
<div class="local-only" v-if="this.localOnly == true">{{ $t('local-only-message') }}</div>
<input v-show="useCw" v-model="cw" :placeholder="$t('annotations')">
<div class="textarea">
<textarea :class="{ with: (files.length != 0 || poll) }"
@@ -110,8 +111,9 @@ export default Vue.extend({
useCw: false,
cw: null,
geo: null,
visibility: this.$store.state.settings.rememberNoteVisibility ? (this.$store.state.device.visibility || this.$store.state.settings.defaultNoteVisibility) : this.$store.state.settings.defaultNoteVisibility,
visibility: 'public',
visibleUsers: [],
localOnly: false,
autocomplete: null,
draghover: false,
recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]'),
@@ -193,6 +195,9 @@ export default Vue.extend({
});
}
// デフォルト公開範囲
this.applyVisibility(this.$store.state.settings.rememberNoteVisibility ? (this.$store.state.device.visibility || this.$store.state.settings.defaultNoteVisibility) : this.$store.state.settings.defaultNoteVisibility);
// 公開以外へのリプライ時は元の公開範囲を引き継ぐ
if (this.reply && ['home', 'followers', 'specified', 'private'].includes(this.reply.visibility)) {
this.visibility = this.reply.visibility;
@@ -363,10 +368,21 @@ export default Vue.extend({
source: this.$refs.visibilityButton
});
w.$once('chosen', v => {
this.visibility = v;
this.applyVisibility(v);
});
},
applyVisibility(v :string) {
const m = v.match(/^local-(.+)/);
if (m) {
this.localOnly = true;
this.visibility = m[1];
} else {
this.localOnly = false;
this.visibility = v;
}
},
addVisibleUser() {
this.$input({
title: this.$t('enter-username')
@@ -407,6 +423,7 @@ export default Vue.extend({
cw: this.useCw ? this.cw || '' : undefined,
visibility: this.visibility,
visibleUserIds: this.visibility == 'specified' ? this.visibleUsers.map(u => u.id) : undefined,
localOnly: this.localOnly,
geo: this.geo ? {
coordinates: [this.geo.longitude, this.geo.latitude],
altitude: this.geo.altitude,
@@ -498,6 +515,7 @@ export default Vue.extend({
border solid 1px var(--primaryAlpha01)
border-radius 4px
transition border-color .2s ease
padding-right 30px
&:hover
border-color var(--primaryAlpha02)
@@ -640,6 +658,10 @@ export default Vue.extend({
margin-right 8px
white-space nowrap
> .local-only
margin 0 0 8px 0
color var(--primary)
> .mk-uploader
margin 8px 0 0 0
padding 8px

View File

@@ -5,7 +5,8 @@
<footer>
<a class="quote" v-if="!quote" @click="onQuote">{{ $t('quote') }}</a>
<ui-button class="button cancel" inline @click="cancel">{{ $t('cancel') }}</ui-button>
<ui-button class="button ok" inline primary @click="ok" :disabled="wait">{{ wait ? this.$t('reposting') : this.$t('renote') }}</ui-button>
<ui-button class="button home" inline :primary="visibility != 'public'" @click="ok('home')" :disabled="wait">{{ wait ? this.$t('reposting') : this.$t('renote-home') }}</ui-button>
<ui-button class="button ok" inline :primary="visibility == 'public'" @click="ok('public')" :disabled="wait">{{ wait ? this.$t('reposting') : this.$t('renote') }}</ui-button>
</footer>
</template>
<template v-if="quote">
@@ -24,14 +25,16 @@ export default Vue.extend({
data() {
return {
wait: false,
quote: false
quote: false,
visibility: this.$store.state.settings.defaultNoteVisibility
};
},
methods: {
ok() {
ok(v: string) {
this.wait = true;
this.$root.api('notes/create', {
renoteId: this.note.id
renoteId: this.note.id,
visibility: v || this.visibility
}).then(data => {
this.$emit('posted');
this.$notify(this.$t('success'));
@@ -81,7 +84,11 @@ export default Vue.extend({
height 40px
&.cancel
right 280px
&.home
right 148px
font-size 13px
&.ok
right 16px

View File

@@ -85,6 +85,9 @@
<option value="followers">{{ $t('@.note-visibility.followers') }}</option>
<option value="specified">{{ $t('@.note-visibility.specified') }}</option>
<option value="private">{{ $t('@.note-visibility.private') }}</option>
<option value="local-public">{{ $t('@.note-visibility.local-public') }}</option>
<option value="local-home">{{ $t('@.note-visibility.local-home') }}</option>
<option value="local-followers">{{ $t('@.note-visibility.local-followers') }}</option>
</ui-select>
</section>
</section>
@@ -130,6 +133,7 @@
<ui-switch v-model="showReplyTarget">{{ $t('show-reply-target') }}</ui-switch>
<ui-switch v-model="showMaps">{{ $t('show-maps') }}</ui-switch>
<ui-switch v-model="disableAnimatedMfm">{{ $t('@.disable-animated-mfm') }}</ui-switch>
<ui-switch v-model="remainDeletedNote">{{ $t('remain-deleted-note') }}</ui-switch>
</section>
<section>
<header>{{ $t('deck-column-align') }}</header>
@@ -529,6 +533,11 @@ export default Vue.extend({
disableAnimatedMfm: {
get() { return this.$store.state.settings.disableAnimatedMfm; },
set(value) { this.$store.dispatch('settings/set', { key: 'disableAnimatedMfm', value }); }
},
remainDeletedNote: {
get() { return this.$store.state.settings.remainDeletedNote; },
set(value) { this.$store.dispatch('settings/set', { key: 'remainDeletedNote', value }); }
}
},
created() {

View File

@@ -1,12 +1,12 @@
<template>
<x-column :menu="menu" :name="name" :column="column" :is-stacked="isStacked">
<span slot="header">
<template v-if="column.type == 'home'"><fa icon="home"/></template>
<template v-if="column.type == 'local'"><fa :icon="['far', 'comments']"/></template>
<template v-if="column.type == 'hybrid'"><fa icon="share-alt"/></template>
<template v-if="column.type == 'global'"><fa icon="globe"/></template>
<template v-if="column.type == 'list'"><fa icon="list"/></template>
<template v-if="column.type == 'hashtag'"><fa icon="hashtag"/></template>
<fa v-if="column.type == 'home'" icon="home"/>
<fa v-if="column.type == 'local'" :icon="['far', 'comments']"/>
<fa v-if="column.type == 'hybrid'" icon="share-alt"/>
<fa v-if="column.type == 'global'" icon="globe"/>
<fa v-if="column.type == 'list'" icon="list"/>
<fa v-if="column.type == 'hashtag'" icon="hashtag"/>
<span>{{ name }}</span>
</span>

View File

@@ -227,6 +227,7 @@ export default define({
background var(--desktopPostFormTextareaBg)
border none
border-bottom solid 1px var(--faceDivider)
padding-right 30px
&:focus
& + .emoji

View File

@@ -115,9 +115,13 @@ import {
faChartLine,
faEllipsisV,
faStickyNote,
faUserClock,
faUserPlus,
faExternalLinkSquareAlt,
faSync,
faArrowLeft,
faMapMarker,
faRobot,
} from '@fortawesome/free-solid-svg-icons';
import {
@@ -138,6 +142,7 @@ import {
faClock as farClock,
faCalendarAlt as farCalendarAlt,
faHdd as farHdd,
faMoon as farMoon,
} from '@fortawesome/free-regular-svg-icons';
import {
@@ -237,9 +242,13 @@ library.add(
faChartLine,
faEllipsisV,
faStickyNote,
faUserClock,
faUserPlus,
faExternalLinkSquareAlt,
faSync,
faArrowLeft,
faMapMarker,
faRobot,
farBell,
farEnvelope,
@@ -258,6 +267,7 @@ library.add(
farClock,
farCalendarAlt,
farHdd,
farMoon,
fabTwitter,
fabGithub,

View File

@@ -385,15 +385,19 @@ export default class MiOS extends EventEmitter {
* @param data パラメータ
*/
@autobind
public api(endpoint: string, data: { [x: string]: any } = {}, forceFetch = false): Promise<{ [x: string]: any }> {
if (++pending === 1) {
spinner = document.createElement('div');
spinner.setAttribute('id', 'wait');
document.body.appendChild(spinner);
public api(endpoint: string, data: { [x: string]: any } = {}, forceFetch = false, silent = false): Promise<{ [x: string]: any }> {
if (!silent) {
if (++pending === 1) {
spinner = document.createElement('div');
spinner.setAttribute('id', 'wait');
document.body.appendChild(spinner);
}
}
const onFinally = () => {
if (--pending === 0) spinner.parentNode.removeChild(spinner);
if (!silent) {
if (--pending === 0) spinner.parentNode.removeChild(spinner);
}
};
const promise = new Promise((resolve, reject) => {

View File

@@ -92,7 +92,7 @@ import parse from '../../../../../mfm/parse';
import MkNoteMenu from '../../../common/views/components/note-menu.vue';
import MkReactionPicker from '../../../common/views/components/reaction-picker.vue';
import XSub from './note.sub.vue';
import { sum } from '../../../../../prelude/array';
import { sum, unique } from '../../../../../prelude/array';
import noteSubscriber from '../../../common/scripts/note-subscriber';
export default Vue.extend({
@@ -143,9 +143,9 @@ export default Vue.extend({
urls(): string[] {
if (this.p.text) {
const ast = parse(this.p.text);
return ast
return unique(ast
.filter(t => (t.type == 'url' || t.type == 'link') && !t.silent)
.map(t => t.url);
.map(t => t.url));
} else {
return null;
}

View File

@@ -16,12 +16,19 @@
<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>
<span>{{ this.$t('reposted-by').substr(this.$t('reposted-by').indexOf('}') + 1) }}</span>
<mk-time :time="note.createdAt"/>
<span class="visibility" v-if="note.visibility != 'public'">
<fa v-if="note.visibility == 'home'" icon="home"/>
<fa v-if="note.visibility == 'followers'" icon="unlock"/>
<fa v-if="note.visibility == 'specified'" icon="envelope"/>
<fa v-if="note.visibility == 'private'" icon="lock"/>
</span>
<span class="localOnly" v-if="note.localOnly == true"><fa icon="heart"/></span>
</div>
<article>
<mk-avatar class="avatar" :user="appearNote.user" v-if="$store.state.device.postStyle != 'smart'"/>
<div class="main">
<mk-note-header class="header" :note="appearNote" :mini="true"/>
<div class="body">
<div class="body" v-if="appearNote.deletedAt == null">
<p v-if="appearNote.cw != null" class="cw">
<span class="text" v-if="appearNote.cw != ''">{{ appearNote.cw }}</span>
<mk-cw-button v-model="showContent"/>
@@ -30,7 +37,7 @@
<div class="text">
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ $t('private') }})</span>
<a class="reply" v-if="appearNote.reply"><fa icon="reply"/></a>
<misskey-flavored-markdown v-if="appearNote.text" :text="appearNote.text" :i="$store.state.i" :class="$style.text" :customEmojis="appearNote.emojis"/>
<misskey-flavored-markdown v-if="appearNote.text" :text="appearNote.text" :i="$store.state.i" :class="$style.text" :custom-emojis="appearNote.emojis"/>
<a class="rp" v-if="appearNote.renote != null">RN:</a>
</div>
<div class="files" v-if="appearNote.files.length > 0">
@@ -43,7 +50,7 @@
</div>
<span class="app" v-if="appearNote.app && $store.state.settings.showVia">via <b>{{ appearNote.app.name }}</b></span>
</div>
<footer>
<footer v-if="appearNote.deletedAt == null">
<mk-reactions-viewer :note="appearNote" ref="reactionsViewer"/>
<button @click="reply()">
<template v-if="appearNote.reply"><fa icon="reply-all"/></template>
@@ -60,6 +67,7 @@
<fa icon="ellipsis-h"/>
</button>
</footer>
<div class="deleted" v-if="appearNote.deletedAt != null">{{ $t('deleted') }}</div>
</div>
</article>
</div>
@@ -163,9 +171,6 @@ export default Vue.extend({
> span
flex-shrink 0
&:last-of-type
margin-right 8px
.name
overflow hidden
flex-shrink 1
@@ -179,6 +184,18 @@ export default Vue.extend({
flex-shrink 0
font-size 0.9em
> .visibility
margin-left 8px
[data-icon]
margin-right 0
> .localOnly
margin-left 4px
[data-icon]
margin-right 0
& + article
padding-top 8px
@@ -339,6 +356,10 @@ export default Vue.extend({
&.reacted
color var(--primary)
> .deleted
color var(--noteText)
opacity 0.7
</style>
<style lang="stylus" module>

View File

@@ -100,8 +100,9 @@ export default Vue.extend({
files: [],
poll: false,
geo: null,
visibility: this.$store.state.settings.rememberNoteVisibility ? (this.$store.state.device.visibility || this.$store.state.settings.defaultNoteVisibility) : this.$store.state.settings.defaultNoteVisibility,
visibility: 'public',
visibleUsers: [],
localOnly: false,
useCw: false,
cw: null,
recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]'),
@@ -183,6 +184,9 @@ export default Vue.extend({
});
}
// デフォルト公開範囲
this.applyVisibility(this.$store.state.settings.rememberNoteVisibility ? (this.$store.state.device.visibility || this.$store.state.settings.defaultNoteVisibility) : this.$store.state.settings.defaultNoteVisibility);
// 公開以外へのリプライ時は元の公開範囲を引き継ぐ
if (this.reply && ['home', 'followers', 'specified', 'private'].includes(this.reply.visibility)) {
this.visibility = this.reply.visibility;
@@ -274,19 +278,19 @@ export default Vue.extend({
compact: true
});
w.$once('chosen', v => {
this.visibility = v;
this.applyVisibility(v);
});
},
addVisibleUser() {
this.$input({
title: this.$t('username-prompt')
}).then(acct => {
if (acct.startsWith('@')) acct = acct.substr(1);
this.$root.api('users/show', parseAcct(acct)).then(user => {
this.visibleUsers.push(user);
});
});
applyVisibility(v :string) {
const m = v.match(/^local-(.+)/);
if (m) {
this.localOnly = true;
this.visibility = m[1];
} else {
this.localOnly = false;
this.visibility = v;
}
},
removeVisibleUser(user) {
@@ -320,6 +324,7 @@ export default Vue.extend({
} : null,
visibility: this.visibility,
visibleUserIds: this.visibility == 'specified' ? this.visibleUsers.map(u => u.id) : undefined,
localOnly: this.localOnly,
viaMobile: viaMobile
}).then(data => {
this.$emit('posted');

View File

@@ -80,6 +80,9 @@
<option value="followers">{{ $t('@.note-visibility.followers') }}</option>
<option value="specified">{{ $t('@.note-visibility.specified') }}</option>
<option value="private">{{ $t('@.note-visibility.private') }}</option>
<option value="local-public">{{ $t('@.note-visibility.local-public') }}</option>
<option value="local-home">{{ $t('@.note-visibility.local-home') }}</option>
<option value="local-followers">{{ $t('@.note-visibility.local-followers') }}</option>
</ui-select>
</section>
</section>

View File

@@ -15,6 +15,7 @@ const defaultSettings = {
tagTimelines: [],
fetchOnScroll: true,
showMaps: true,
remainDeletedNote: false,
showPostFormOnTopOfTl: false,
suggestRecentHashtags: true,
showClockOnHeader: true,

View File

@@ -26,6 +26,13 @@ props:
ja-JP: "モバイル端末から投稿したか否か(自己申告であることに留意)"
en-US: "Whether this note sent via a mobile device"
localOnly:
type: "boolean"
optional: true
desc:
ja-JP: "ローカルのみに公開する投稿か否か"
en-US: "Whether this note is no federation"
text:
type: "string"
optional: true

View File

@@ -112,7 +112,12 @@ async function init(): Promise<Config> {
Logger.info('Welcome to Misskey!');
Logger.info(`<<< Misskey v${pkg.version} >>>`);
new Logger('Deps').info(`Node.js ${process.version}`);
new Logger('Nodejs').info(`Version ${process.version}`);
if (lessThan(process.version.slice(1).split('.').map(x => parseInt(x, 10)), [10, 0, 0])) {
new Logger('Nodejs').error(`Node.js version is less than 10.0.0. Please upgrade it.`);
process.exit(1);
}
await MachineInfo.show();
EnvironmentInfo.show();
@@ -135,6 +140,11 @@ async function init(): Promise<Config> {
configLogger.succ('Loaded');
if (config.port == null) {
Logger.error('The port is not configured. Please configure port.');
process.exit(1);
}
if (process.platform === 'linux' && !isRoot() && config.port < 1024) {
Logger.error('You need root privileges to listen on port below 1024 on Linux');
process.exit(1);

View File

@@ -53,6 +53,12 @@ const handlers: { [key: string]: (window: any, token: any, mentionedRemoteUsers:
document.body.appendChild(element);
},
math({ document }, { formula }) {
const element = document.createElement('code');
element.textContent = formula;
document.body.appendChild(element);
},
link({ document }, { url, title }) {
const a = document.createElement('a');
a.href = url;

View File

@@ -8,7 +8,9 @@ export type TextElementHashtag = {
hashtag: string;
};
export default function(text: string, isBegin: boolean) {
export default function(text: string, before: string) {
const isBegin = before == '';
if (!(/^\s#[^\s\.,!\?#]+/.test(text) || (isBegin && /^#[^\s\.,!\?#]+/.test(text)))) return null;
const isHead = text.startsWith('#');
const hashtag = text.match(/^\s?#[^\s\.,!\?#]+/)[0];

View File

@@ -0,0 +1,20 @@
/**
* Math
*/
export type TextElementMath = {
type: 'math';
content: string;
formula: string;
};
export default function(text: string) {
const match = text.match(/^\\\((.+?)\\\)/);
if (!match) return null;
const math = match[0];
return {
type: 'math',
content: math,
formula: match[1]
} as TextElementMath;
}

View File

@@ -12,9 +12,10 @@ export type TextElementMention = {
host: string;
};
export default function(text: string) {
export default function(text: string, before: string) {
const match = text.match(/^@[a-z0-9_]+(?:@[a-z0-9\.\-]+[a-z0-9])?/i);
if (!match) return null;
if (/[a-zA-Z0-9]$/.test(before)) return null;
const mention = match[0];
const { username, host } = parseAcct(mention.substr(1));
const canonical = host != null ? `@${username}@${toUnicode(host)}` : mention;

View File

@@ -8,7 +8,9 @@ export type TextElementQuote = {
quote: string;
};
export default function(text: string, isBegin: boolean) {
export default function(text: string, before: string) {
const isBegin = before == '';
const match = text.match(/^"([\s\S]+?)\n"/) || text.match(/^\n>([\s\S]+?)(\n\n|$)/) ||
(isBegin ? text.match(/^>([\s\S]+?)(\n\n|$)/) : null);

View File

@@ -8,7 +8,9 @@ export type TextElementTitle = {
title: string;
};
export default function(text: string, isBegin: boolean) {
export default function(text: string, before: string) {
const isBegin = before == '';
const match = isBegin ? text.match(/^(【|\[)(.+?)(】|])\n/) : text.match(/^\n(【|\[)(.+?)(】|])\n/);
if (!match) return null;
return {

View File

@@ -8,10 +8,13 @@ export type TextElementUrl = {
url: string;
};
export default function(text: string) {
const match = text.match(/^https?:\/\/[\w\/:%#@\$&\?!\(\)\[\]~\.=\+\-]+/);
export default function(text: string, before: string) {
const match = text.match(/^https?:\/\/[\w\/:%#@\$&\?!\(\)\[\]~\.,=\+\-]+/);
if (!match) return null;
const url = match[0];
let url = match[0];
if (url.endsWith('.')) url = url.substr(0, url.lastIndexOf('.'));
if (url.endsWith(',')) url = url.substr(0, url.lastIndexOf(','));
if (url.endsWith(')') && before.endsWith('(')) url = url.substr(0, url.lastIndexOf(')'));
return {
type: 'url',
content: url,

View File

@@ -8,6 +8,7 @@ import { TextElementCode } from './elements/code';
import { TextElementEmoji } from './elements/emoji';
import { TextElementHashtag } from './elements/hashtag';
import { TextElementInlineCode } from './elements/inline-code';
import { TextElementMath } from './elements/math';
import { TextElementLink } from './elements/link';
import { TextElementMention } from './elements/mention';
import { TextElementQuote } from './elements/quote';
@@ -29,6 +30,7 @@ const elements = [
require('./elements/hashtag'),
require('./elements/code'),
require('./elements/inline-code'),
require('./elements/math'),
require('./elements/quote'),
require('./elements/emoji'),
require('./elements/search'),
@@ -42,6 +44,7 @@ export type TextElement = { type: 'text', content: string }
| TextElementEmoji
| TextElementHashtag
| TextElementInlineCode
| TextElementMath
| TextElementLink
| TextElementMention
| TextElementQuote
@@ -49,7 +52,7 @@ export type TextElement = { type: 'text', content: string }
| TextElementTitle
| TextElementUrl
| TextElementMotion;
export type TextElementProcessor = (text: string, isBegin: boolean) => TextElement | TextElement[];
export type TextElementProcessor = (text: string, before: string) => TextElement | TextElement[];
export default (source: string): TextElement[] => {
if (source == null || source == '') {
@@ -65,12 +68,10 @@ export default (source: string): TextElement[] => {
}
}
let i = 0;
// パース
while (source != '') {
const parsed = elements.some(el => {
let _tokens = el(source, i == 0);
let _tokens = el(source, tokens.map(token => token.content).join(''));
if (_tokens) {
if (!Array.isArray(_tokens)) {
_tokens = [_tokens];
@@ -88,8 +89,6 @@ export default (source: string): TextElement[] => {
content: source[0]
});
}
i++;
}
const combineText = (es: TextElement[]): TextElement =>

View File

@@ -50,6 +50,7 @@ export type INote = {
userId: mongo.ObjectID;
appId: mongo.ObjectID;
viaMobile: boolean;
localOnly: boolean;
renoteCount: number;
repliesCount: number;
reactionCounts: any;

View File

@@ -6,6 +6,8 @@ export function createHttpJob(data: any) {
}
export function deliver(user: ILocalUser, content: any, to: any) {
if (content == null) return;
createHttpJob({
type: 'deliver',
user,

View File

@@ -92,7 +92,7 @@ export default async (job: bq.Job, done: any): Promise<void> => {
done();
return;
}
//#region Log
publishApLogStream({
direction: 'in',

View File

@@ -35,17 +35,11 @@ export default async function(resolver: Resolver, actor: IRemoteUser, activity:
log(`Creating the (Re)Note: ${uri}`);
//#region Visibility
let visibility = 'public';
const visibility = getVisibility(activity.to, activity.cc, actor);
let visibleUsers: IUser[] = [];
if (!note.to.includes('https://www.w3.org/ns/activitystreams#Public')) {
if (note.cc.includes('https://www.w3.org/ns/activitystreams#Public')) {
visibility = 'home';
} else if (note.to.includes(`${actor.uri}/followers`)) { // TODO: person.followerと照合するべき
visibility = 'followers';
} else {
visibility = 'specified';
visibleUsers = await Promise.all(note.to.map(uri => resolvePerson(uri)));
}
if (visibility == 'specified') {
visibleUsers = await Promise.all(note.to.map(uri => resolvePerson(uri)));
}
//#endergion
@@ -57,3 +51,22 @@ export default async function(resolver: Resolver, actor: IRemoteUser, activity:
uri
});
}
type visibility = 'public' | 'home' | 'followers' | 'specified' | 'private';
function getVisibility(to: string[], cc: string[], actor: IRemoteUser): visibility {
const PUBLIC = 'https://www.w3.org/ns/activitystreams#Public';
to = to || [];
cc = cc || [];
if (to.includes(PUBLIC)) {
return 'public';
} else if (cc.includes(PUBLIC)) {
return 'home';
} else if (to.includes(`${actor.uri}/followers`)) {
return 'followers';
} else {
return 'specified';
}
}

View File

@@ -116,6 +116,7 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
cw: note.summary,
text: text,
viaMobile: false,
localOnly: false,
geo: undefined,
visibility,
visibleUsers,

View File

@@ -4,13 +4,26 @@ import { INote } from '../../../models/note';
export default (object: any, note: INote) => {
const attributedTo = `${config.url}/users/${note.userId}`;
let to: string[] = [];
let cc: string[] = [];
if (note.visibility == 'public') {
to = ['https://www.w3.org/ns/activitystreams#Public'];
cc = [`${attributedTo}/followers`];
} else if (note.visibility == 'home') {
to = [`${attributedTo}/followers`];
cc = ['https://www.w3.org/ns/activitystreams#Public'];
} else {
return null;
}
return {
id: `${config.url}/notes/${note._id}/activity`,
actor: `${config.url}/users/${note.userId}`,
type: 'Announce',
published: note.createdAt.toISOString(),
to: ['https://www.w3.org/ns/activitystreams#Public'],
cc: [attributedTo, `${attributedTo}/followers`],
to,
cc,
object
};
};

View File

@@ -2,6 +2,8 @@ import config from '../../../config';
import * as uuid from 'uuid';
export default (x: any) => {
if (x == null) return null;
if (x !== null && typeof x === 'object' && x.id == null) {
x.id = `${config.url}/${uuid.v4()}`;
}

View File

@@ -66,7 +66,8 @@ router.get('/notes/:note', async (ctx, next) => {
const note = await Note.findOne({
_id: new mongo.ObjectID(ctx.params.note),
visibility: { $in: ['public', 'home'] }
visibility: { $in: ['public', 'home'] },
localOnly: { $ne: true }
});
if (note === null) {
@@ -83,7 +84,8 @@ router.get('/notes/:note', async (ctx, next) => {
router.get('/notes/:note/activity', async ctx => {
const note = await Note.findOne({
_id: new mongo.ObjectID(ctx.params.note),
visibility: { $in: ['public', 'home'] }
visibility: { $in: ['public', 'home'] },
localOnly: { $ne: true }
});
if (note === null) {

View File

@@ -55,7 +55,8 @@ export default async (ctx: Router.IRouterContext) => {
const query = {
userId: user._id,
visibility: { $in: ['public', 'home'] }
visibility: { $in: ['public', 'home'] },
localOnly: { $ne: true }
} as any;
if (sinceId) {

View File

@@ -68,6 +68,10 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
maxNoteTextLength: instance.maxNoteTextLength,
emojis: emojis,
enableTwitterIntegration: instance.enableTwitterIntegration,
enableGithubIntegration: instance.enableGithubIntegration,
enableDiscordIntegration: instance.enableDiscordIntegration,
};
if (ps.detail) {
@@ -89,13 +93,10 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
response.hidedTags = instance.hidedTags;
response.recaptchaSecretKey = instance.recaptchaSecretKey;
response.proxyAccount = instance.proxyAccount;
response.enableTwitterIntegration = instance.enableTwitterIntegration;
response.twitterConsumerKey = instance.twitterConsumerKey;
response.twitterConsumerSecret = instance.twitterConsumerSecret;
response.enableGithubIntegration = instance.enableGithubIntegration;
response.githubClientId = instance.githubClientId;
response.githubClientSecret = instance.githubClientSecret;
response.enableDiscordIntegration = instance.enableDiscordIntegration;
response.discordClientId = instance.discordClientId;
response.discordClientSecret = instance.discordClientSecret;
}

View File

@@ -74,6 +74,14 @@ export const meta = {
}
},
localOnly: {
validator: $.bool.optional,
default: false,
desc: {
'ja-JP': 'ローカルのみに投稿か否か。'
}
},
geo: {
validator: $.obj({
coordinates: $.arr().length(2)
@@ -226,6 +234,7 @@ export default define(meta, (ps, user, app) => new Promise(async (res, rej) => {
cw: ps.cw,
app,
viaMobile: ps.viaMobile,
localOnly: ps.localOnly,
visibility: ps.visibility,
visibleUsers,
geo: ps.geo

View File

@@ -75,9 +75,9 @@ handler.on('status', event => {
const parentState = parentStatuses[0].state;
const stillFailed = parentState == 'failure' || parentState == 'error';
if (stillFailed) {
post(`**BUILD STILL FAILED⚠**: ?[${commit.commit.message}](${commit.html_url})`);
post(`⚠️**BUILD STILL FAILED**⚠️: ?[${commit.commit.message}](${commit.html_url})`);
} else {
post(`**🚨BUILD FAILED🚨**: →→→?[${commit.commit.message}](${commit.html_url})←←←`);
post(`🚨**BUILD FAILED**🚨: →→→?[${commit.commit.message}](${commit.html_url})←←←`);
}
});
break;
@@ -87,7 +87,7 @@ handler.on('status', event => {
handler.on('push', event => {
const ref = event.ref;
switch (ref) {
case 'refs/heads/master':
case 'refs/heads/develop':
const pusher = event.pusher;
const compare = event.compare;
const commits: any[] = event.commits;
@@ -96,10 +96,6 @@ handler.on('push', event => {
commits.reverse().map(commit => `・[?[${commit.id.substr(0, 7)}](${commit.url})] ${commit.message.split('\n')[0]}`).join('\n'),
].join('\n'));
break;
case 'refs/heads/release':
const commit = event.commits[0];
post(`RELEASED: ${commit.message}`);
break;
}
});
@@ -128,6 +124,17 @@ handler.on('issue_comment', event => {
post(text);
});
handler.on('release', event => {
const action = event.action;
const release = event.release;
let text: string;
switch (action) {
case 'published': text = `🎁 **NEW RELEASE**: [${release.tag_name}](${release.html_url}) is out now. Enjoy!`; break;
default: return;
}
post(text);
});
handler.on('watch', event => {
const sender = event.sender;
post(`(((⭐️))) Starred by **${sender.login}** (((⭐️)))`, false);

View File

@@ -95,6 +95,7 @@ type Option = {
geo?: any;
poll?: any;
viaMobile?: boolean;
localOnly?: boolean;
cw?: string;
visibility?: string;
visibleUsers?: IUser[];
@@ -109,6 +110,7 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
if (data.createdAt == null) data.createdAt = new Date();
if (data.visibility == null) data.visibility = 'public';
if (data.viaMobile == null) data.viaMobile = false;
if (data.localOnly == null) data.localOnly = false;
if (data.visibleUsers) {
data.visibleUsers = erase(null, data.visibleUsers);
@@ -139,6 +141,16 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
return rej('Renote target is private of others');
}
// ローカルのみをRenoteしたらローカルのみにする
if (data.renote && data.renote.localOnly) {
data.localOnly = true;
}
// ローカルのみにリプライしたらローカルのみにする
if (data.reply && data.reply.localOnly) {
data.localOnly = true;
}
if (data.text) {
data.text = data.text.trim();
}
@@ -308,6 +320,8 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
});
async function renderActivity(data: Option, note: INote) {
if (data.localOnly) return null;
const content = data.renote && data.text == null && data.poll == null && (data.files == null || data.files.length == 0)
? renderAnnounce(data.renote.uri ? data.renote.uri : `${config.url}/notes/${data.renote._id}`, note)
: renderCreate(await renderNote(note, false), note);
@@ -389,6 +403,7 @@ async function insertNote(user: IUser, data: Option, tags: string[], emojis: str
emojis,
userId: user._id,
viaMobile: data.viaMobile,
localOnly: data.localOnly,
geo: data.geo || null,
appId: data.app ? data.app._id : null,
visibility: data.visibility,

View File

@@ -13,11 +13,11 @@ describe('Text', () => {
const tokens = analyze('@himawari @hima_sub@namori.net お腹ペコい :cat: #yryr');
assert.deepEqual([
{ type: 'mention', content: '@himawari', canonical: '@himawari', username: 'himawari', host: null },
{ type: 'text', content: ' '},
{ type: 'text', content: ' ' },
{ type: 'mention', content: '@hima_sub@namori.net', canonical: '@hima_sub@namori.net', username: 'hima_sub', host: 'namori.net' },
{ type: 'text', content: ' お腹ペコい ' },
{ type: 'emoji', content: ':cat:', name: 'cat'},
{ type: 'text', content: ' '},
{ type: 'emoji', content: ':cat:', name: 'cat' },
{ type: 'text', content: ' ' },
{ type: 'hashtag', content: '#yryr', hashtag: 'yryr' }
], tokens);
});
@@ -82,7 +82,7 @@ describe('Text', () => {
{ type: 'text', content: ' お腹ペコい' }
], tokens);
});
/*
it('ignore', () => {
const tokens = analyze('idolm@ster');
assert.deepEqual([
@@ -91,20 +91,19 @@ describe('Text', () => {
const tokens2 = analyze('@a\n@b\n@c');
assert.deepEqual([
{ type: 'mention', content: '@a', username: 'a', host: null },
{ type: 'mention', content: '@a', canonical: '@a', username: 'a', host: null },
{ type: 'text', content: '\n' },
{ type: 'mention', content: '@b', username: 'b', host: null },
{ type: 'mention', content: '@b', canonical: '@b', username: 'b', host: null },
{ type: 'text', content: '\n' },
{ type: 'mention', content: '@c', username: 'c', host: null }
{ type: 'mention', content: '@c', canonical: '@c', username: 'c', host: null }
], tokens2);
const tokens3 = analyze('**x**@a');
assert.deepEqual([
{ type: 'bold', content: '**x**', bold: 'x' },
{ type: 'mention', content: '@a', username: 'a', host: null }
{ type: 'mention', content: '@a', canonical: '@a', username: 'a', host: null }
], tokens3);
});
*/
});
it('hashtag', () => {
@@ -159,13 +158,81 @@ describe('Text', () => {
], tokens5);
});
it('url', () => {
const tokens = analyze('https://himasaku.net');
assert.deepEqual([{
type: 'url',
content: 'https://himasaku.net',
url: 'https://himasaku.net'
}], tokens);
describe('url', () => {
it('simple', () => {
const tokens = analyze('https://example.com');
assert.deepEqual([{
type: 'url',
content: 'https://example.com',
url: 'https://example.com'
}], tokens);
});
it('ignore trailing period', () => {
const tokens = analyze('https://example.com.');
assert.deepEqual([{
type: 'url',
content: 'https://example.com',
url: 'https://example.com'
}, {
type: 'text', content: '.'
}], tokens);
});
it('with comma', () => {
const tokens = analyze('https://example.com/foo?bar=a,b');
assert.deepEqual([{
type: 'url',
content: 'https://example.com/foo?bar=a,b',
url: 'https://example.com/foo?bar=a,b'
}], tokens);
});
it('ignore trailing comma', () => {
const tokens = analyze('https://example.com/foo, bar');
assert.deepEqual([{
type: 'url',
content: 'https://example.com/foo',
url: 'https://example.com/foo'
}, {
type: 'text', content: ', bar'
}], tokens);
});
it('with brackets', () => {
const tokens = analyze('https://example.com/foo(bar)');
assert.deepEqual([{
type: 'url',
content: 'https://example.com/foo(bar)',
url: 'https://example.com/foo(bar)'
}], tokens);
});
it('ignore parent brackets', () => {
const tokens = analyze('(https://example.com/foo)');
assert.deepEqual([{
type: 'text', content: '('
}, {
type: 'url',
content: 'https://example.com/foo',
url: 'https://example.com/foo'
}, {
type: 'text', content: ')'
}], tokens);
});
it('ignore parent brackets with internal brackets', () => {
const tokens = analyze('(https://example.com/foo(bar))');
assert.deepEqual([{
type: 'text', content: '('
}, {
type: 'url',
content: 'https://example.com/foo(bar)',
url: 'https://example.com/foo(bar)'
}, {
type: 'text', content: ')'
}], tokens);
});
});
it('link', () => {
@@ -210,6 +277,15 @@ describe('Text', () => {
assert.equal(tokens[0].content, '`var x = "Strawberry Pasta";`');
});
it('math', () => {
const fomula = 'x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}';
const text = `\\(${fomula}\\)`;
const tokens = analyze(text);
assert.deepEqual([
{ type: 'math', content: text, formula: fomula }
], tokens);
});
it('search', () => {
const tokens1 = analyze('a b c 検索');
assert.deepEqual([
@@ -236,17 +312,17 @@ describe('Text', () => {
const tokens1 = analyze('【yee】\nhaw');
assert.deepEqual(
{ type: 'title', content: '【yee】\n', title: 'yee' }
, tokens1[0]);
, tokens1[0]);
const tokens2 = analyze('[yee]\nhaw');
assert.deepEqual(
{ type: 'title', content: '[yee]\n', title: 'yee' }
, tokens2[0]);
, tokens2[0]);
const tokens3 = analyze('a [a]\nb [b]\nc [c]');
assert.deepEqual(
{ type: 'text', content: 'a [a]\nb [b]\nc [c]' }
, tokens3[0]);
, tokens3[0]);
const tokens4 = analyze('foo\n【bar】\nbuzz');
assert.deepEqual([