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. 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. 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`. 1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`.
2. `cp .config/mongo_initdb_example.js .config/mongo_initdb.js` Copy the `.config/mongo_initdb_example.js` and rename it to `mongo_initdb.js`. 2. `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. *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 ### Launch normally
Just `docker-compose up -d`. GLHF! 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` 1. `git fetch`
2. `git stash` 2. `git stash`
3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` 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 6. Check [ChangeLog](../CHANGELOG.md) for migration information
7. `docker-compose stop && docker-compose up -d` 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` `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 *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 : In debian for exemple :
``` ```
@@ -32,7 +32,7 @@ Please install and setup these softwares:
*3.* Setup MongoDB *3.* Setup MongoDB
---------------------------------------------------------------- ----------------------------------------------------------------
In root : As root:
1. `mongo` Go to the mongo shell 1. `mongo` Go to the mongo shell
2. `use misskey` Use the misskey database 2. `use misskey` Use the misskey database
3. `db.users.save( {dummy:"dummy"} )` Write dummy data to initialize the db. 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) 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. 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: 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 ``` shell
npm install web-push -g npm install web-push -g
web-push generate-vapid-keys 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`. 1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`.
2. Edit `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`. 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` 1. `git fetch`
2. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` 2. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)`
3. `npm install` 3. `npm install`

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,7 +5,7 @@
const fs = require('fs'); const fs = require('fs');
const yaml = require('js-yaml'); 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 loadLocale = lang => yaml.safeLoad(fs.readFileSync(`${__dirname}/${lang}.yml`, 'utf-8'));
const locales = langs.map(lang => ({ [lang]: loadLocale(lang) })); const locales = langs.map(lang => ({ [lang]: loadLocale(lang) }));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -8,13 +8,19 @@
<p>{{ $t('@.ai-chan-kawaii') }}</p> <p>{{ $t('@.ai-chan-kawaii') }}</p>
</header> </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 v-if="stats" class="stats">
<div> <div>
<div> <div>
<div><fa icon="user"/></div> <div><fa icon="user"/></div>
<div> <div>
<span>{{ $t('accounts') }}</span> <span>{{ $t('accounts') }}</span>
<b class="primary">{{ stats.originalUsersCount | number }}</b> <b>{{ stats.originalUsersCount | number }}</b>
</div> </div>
</div> </div>
<div> <div>
@@ -27,7 +33,7 @@
<div><fa icon="pencil-alt"/></div> <div><fa icon="pencil-alt"/></div>
<div> <div>
<span>{{ $t('notes') }}</span> <span>{{ $t('notes') }}</span>
<b class="primary">{{ stats.originalNotesCount | number }}</b> <b>{{ stats.originalNotesCount | number }}</b>
</div> </div>
</div> </div>
<div> <div>
@@ -84,6 +90,8 @@ import XCpuMemory from "./cpu-memory.vue";
import XCharts from "./charts.vue"; import XCharts from "./charts.vue";
import XApLog from "./ap-log.vue"; import XApLog from "./ap-log.vue";
import { faDatabase } from '@fortawesome/free-solid-svg-icons'; import { faDatabase } from '@fortawesome/free-solid-svg-icons';
import MarqueeText from 'vue-marquee-text-component';
import randomColor from 'randomcolor';
export default Vue.extend({ export default Vue.extend({
i18n: i18n('admin/views/dashboard.vue'), i18n: i18n('admin/views/dashboard.vue'),
@@ -91,7 +99,8 @@ export default Vue.extend({
components: { components: {
XCpuMemory, XCpuMemory,
XCharts, XCharts,
XApLog XApLog,
MarqueeText
}, },
data() { data() {
@@ -99,6 +108,8 @@ export default Vue.extend({
stats: null, stats: null,
connection: null, connection: null,
meta: null, meta: null,
instances: [],
clock: null,
faDatabase faDatabase
}; };
}, },
@@ -106,22 +117,40 @@ export default Vue.extend({
created() { created() {
this.connection = this.$root.stream.useSharedConnection('serverStats'); this.connection = this.$root.stream.useSharedConnection('serverStats');
this.updateStats();
this.clock = setInterval(this.updateStats, 1000);
this.$root.getMeta().then(meta => { this.$root.getMeta().then(meta => {
this.meta = meta; this.meta = meta;
}); });
this.$root.api('stats').then(stats => { this.$root.api('instances', {
this.stats = stats; sort: '+notes'
}).then(instances => {
instances.forEach(i => {
i.bg = randomColor({
seed: i.host,
luminosity: 'dark'
});
});
this.instances = instances;
}); });
}, },
beforeDestroy() { beforeDestroy() {
this.connection.dispose(); this.connection.dispose();
clearInterval(this.clock);
}, },
methods: { methods: {
setChartSrc(src) { setChartSrc(src) {
this.$refs.charts.setSrc(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 > header
display flex display flex
margin-bottom 16px
padding-bottom 16px padding-bottom 16px
border-bottom solid 1px var(--adminDashboardHeaderBorder) border-bottom solid 1px var(--adminDashboardHeaderBorder)
color var(--adminDashboardHeaderFg) color var(--adminDashboardHeaderFg)
@@ -161,6 +189,20 @@ export default Vue.extend({
margin-left auto margin-left auto
margin-right 0 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 > .stats
display flex display flex
justify-content space-between justify-content space-between
@@ -201,9 +243,6 @@ export default Vue.extend({
> b > b
display block display block
&.primary
color var(--primary)
> div:last-child > div:last-child
display flex display flex
padding 6px 16px 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('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('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('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('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('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('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('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> </ul>
<div class="back-to-misskey"> <div class="back-to-misskey">
<a href="/"><fa :icon="faArrowLeft"/> {{ $t('back-to-misskey') }}</a> <a href="/"><fa :icon="faArrowLeft"/> {{ $t('back-to-misskey') }}</a>
@@ -37,11 +37,6 @@
</div> </div>
</nav> </nav>
<main> <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 class="page">
<div v-if="page == 'dashboard'"><x-dashboard/></div> <div v-if="page == 'dashboard'"><x-dashboard/></div>
<div v-if="page == 'instance'"><x-instance/></div> <div v-if="page == 'instance'"><x-instance/></div>
@@ -68,10 +63,8 @@ import XEmoji from "./emoji.vue";
import XAnnouncements from "./announcements.vue"; import XAnnouncements from "./announcements.vue";
import XHashtags from "./hashtags.vue"; import XHashtags from "./hashtags.vue";
import XUsers from "./users.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 { faGrin } from '@fortawesome/free-regular-svg-icons';
import MarqueeText from 'vue-marquee-text-component';
import randomColor from 'randomcolor';
// Detect the user agent // Detect the user agent
const ua = navigator.userAgent.toLowerCase(); const ua = navigator.userAgent.toLowerCase();
@@ -86,8 +79,7 @@ export default Vue.extend({
XEmoji, XEmoji,
XAnnouncements, XAnnouncements,
XHashtags, XHashtags,
XUsers, XUsers
MarqueeText
}, },
provide: { provide: {
isMobile isMobile
@@ -98,25 +90,12 @@ export default Vue.extend({
version, version,
isMobile, isMobile,
navOpend: !isMobile, navOpend: !isMobile,
instances: [],
faGrin, faGrin,
faArrowLeft, 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: { methods: {
nav(page: string) { nav(page: string) {
this.page = page; this.page = page;
@@ -287,22 +266,8 @@ export default Vue.extend({
width 100% width 100%
padding 0 0 0 250px 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 > .page
max-width 1300px max-width 1150px
&.isMobile &.isMobile
> main > main

View File

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

View File

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

View File

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

View File

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

View File

@@ -12,9 +12,9 @@
</ui-input> </ui-input>
<ui-input v-if="user && user.twoFactorEnabled" v-model="token" type="number" required styl="fill"/> <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> <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 v-if="meta && meta.enableTwitterIntegration" 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 v-if="meta && meta.enableGithubIntegration" 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.enableDiscordIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/discord`">{{ $t('signin-with-discord') /* TODO: Make these layouts better */ }}</a></p>
</form> </form>
</template> </template>
@@ -41,9 +41,15 @@ export default Vue.extend({
password: '', password: '',
token: '', token: '',
apiUrl, apiUrl,
host: toUnicode(host) host: toUnicode(host),
meta: null
}; };
}, },
created() {
this.$root.getMeta().then(meta => {
this.meta = meta;
});
},
methods: { methods: {
onUsernameChange() { onUsernameChange() {
this.$root.api('users/show', { 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 >= 3600 ? this.$t('@.time.hours_ago') .replace('{}', (~~(ago / 3600)).toString()) :
ago >= 60 ? this.$t('@.time.minutes_ago').replace('{}', (~~(ago / 60)).toString()) : ago >= 60 ? this.$t('@.time.minutes_ago').replace('{}', (~~(ago / 60)).toString()) :
ago >= 10 ? this.$t('@.time.seconds_ago').replace('{}', (~~(ago % 60)).toString()) : ago >= 10 ? this.$t('@.time.seconds_ago').replace('{}', (~~(ago % 60)).toString()) :
ago >= 0 ? this.$t('@.time.just_now') : ago >= -1 ? this.$t('@.time.just_now') :
ago < 0 ? this.$t('@.time.future') : ago < -1 ? this.$t('@.time.future') :
this.$t('@.time.unknown')); this.$t('@.time.unknown'));
} }
}, },

View File

@@ -35,6 +35,25 @@
<span>{{ $t('private') }}</span> <span>{{ $t('private') }}</span>
</div> </div>
</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>
</div> </div>
</template> </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>Maintainer: <b><a :href="'mailto:' + meta.maintainer.email" target="_blank">{{ meta.maintainer.name }}</a></b></p>
<p>Machine: {{ meta.machine }}</p> <p>Machine: {{ meta.machine }}</p>
<p>Node: {{ meta.node }}</p> <p>Node: {{ meta.node }}</p>
<p>Version: {{ meta.version }} </p>
</div> </div>
</template> </template>

View File

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

View File

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

View File

@@ -14,6 +14,7 @@
<b>{{ $t('recent-tags') }}:</b> <b>{{ $t('recent-tags') }}:</b>
<a v-for="tag in recentHashtags.slice(0, 5)" @click="addTag(tag)" :title="$t('click-to-tagging')">#{{ tag }}</a> <a v-for="tag in recentHashtags.slice(0, 5)" @click="addTag(tag)" :title="$t('click-to-tagging')">#{{ tag }}</a>
</div> </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')"> <input v-show="useCw" v-model="cw" :placeholder="$t('annotations')">
<div class="textarea"> <div class="textarea">
<textarea :class="{ with: (files.length != 0 || poll) }" <textarea :class="{ with: (files.length != 0 || poll) }"
@@ -110,8 +111,9 @@ export default Vue.extend({
useCw: false, useCw: false,
cw: null, cw: null,
geo: 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: [], visibleUsers: [],
localOnly: false,
autocomplete: null, autocomplete: null,
draghover: false, draghover: false,
recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]'), 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)) { if (this.reply && ['home', 'followers', 'specified', 'private'].includes(this.reply.visibility)) {
this.visibility = this.reply.visibility; this.visibility = this.reply.visibility;
@@ -363,10 +368,21 @@ export default Vue.extend({
source: this.$refs.visibilityButton source: this.$refs.visibilityButton
}); });
w.$once('chosen', v => { 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() { addVisibleUser() {
this.$input({ this.$input({
title: this.$t('enter-username') title: this.$t('enter-username')
@@ -407,6 +423,7 @@ export default Vue.extend({
cw: this.useCw ? this.cw || '' : undefined, cw: this.useCw ? this.cw || '' : undefined,
visibility: this.visibility, visibility: this.visibility,
visibleUserIds: this.visibility == 'specified' ? this.visibleUsers.map(u => u.id) : undefined, visibleUserIds: this.visibility == 'specified' ? this.visibleUsers.map(u => u.id) : undefined,
localOnly: this.localOnly,
geo: this.geo ? { geo: this.geo ? {
coordinates: [this.geo.longitude, this.geo.latitude], coordinates: [this.geo.longitude, this.geo.latitude],
altitude: this.geo.altitude, altitude: this.geo.altitude,
@@ -498,6 +515,7 @@ export default Vue.extend({
border solid 1px var(--primaryAlpha01) border solid 1px var(--primaryAlpha01)
border-radius 4px border-radius 4px
transition border-color .2s ease transition border-color .2s ease
padding-right 30px
&:hover &:hover
border-color var(--primaryAlpha02) border-color var(--primaryAlpha02)
@@ -640,6 +658,10 @@ export default Vue.extend({
margin-right 8px margin-right 8px
white-space nowrap white-space nowrap
> .local-only
margin 0 0 8px 0
color var(--primary)
> .mk-uploader > .mk-uploader
margin 8px 0 0 0 margin 8px 0 0 0
padding 8px padding 8px

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -385,15 +385,19 @@ export default class MiOS extends EventEmitter {
* @param data パラメータ * @param data パラメータ
*/ */
@autobind @autobind
public api(endpoint: string, data: { [x: string]: any } = {}, forceFetch = false): Promise<{ [x: string]: any }> { public api(endpoint: string, data: { [x: string]: any } = {}, forceFetch = false, silent = false): Promise<{ [x: string]: any }> {
if (++pending === 1) { if (!silent) {
spinner = document.createElement('div'); if (++pending === 1) {
spinner.setAttribute('id', 'wait'); spinner = document.createElement('div');
document.body.appendChild(spinner); spinner.setAttribute('id', 'wait');
document.body.appendChild(spinner);
}
} }
const onFinally = () => { const onFinally = () => {
if (--pending === 0) spinner.parentNode.removeChild(spinner); if (!silent) {
if (--pending === 0) spinner.parentNode.removeChild(spinner);
}
}; };
const promise = new Promise((resolve, reject) => { 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 MkNoteMenu from '../../../common/views/components/note-menu.vue';
import MkReactionPicker from '../../../common/views/components/reaction-picker.vue'; import MkReactionPicker from '../../../common/views/components/reaction-picker.vue';
import XSub from './note.sub.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'; import noteSubscriber from '../../../common/scripts/note-subscriber';
export default Vue.extend({ export default Vue.extend({
@@ -143,9 +143,9 @@ export default Vue.extend({
urls(): string[] { urls(): string[] {
if (this.p.text) { if (this.p.text) {
const ast = parse(this.p.text); const ast = parse(this.p.text);
return ast return unique(ast
.filter(t => (t.type == 'url' || t.type == 'link') && !t.silent) .filter(t => (t.type == 'url' || t.type == 'link') && !t.silent)
.map(t => t.url); .map(t => t.url));
} else { } else {
return null; return null;
} }

View File

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

View File

@@ -100,8 +100,9 @@ export default Vue.extend({
files: [], files: [],
poll: false, poll: false,
geo: 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: [], visibleUsers: [],
localOnly: false,
useCw: false, useCw: false,
cw: null, cw: null,
recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]'), 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)) { if (this.reply && ['home', 'followers', 'specified', 'private'].includes(this.reply.visibility)) {
this.visibility = this.reply.visibility; this.visibility = this.reply.visibility;
@@ -274,19 +278,19 @@ export default Vue.extend({
compact: true compact: true
}); });
w.$once('chosen', v => { w.$once('chosen', v => {
this.visibility = v; this.applyVisibility(v);
}); });
}, },
addVisibleUser() { applyVisibility(v :string) {
this.$input({ const m = v.match(/^local-(.+)/);
title: this.$t('username-prompt') if (m) {
}).then(acct => { this.localOnly = true;
if (acct.startsWith('@')) acct = acct.substr(1); this.visibility = m[1];
this.$root.api('users/show', parseAcct(acct)).then(user => { } else {
this.visibleUsers.push(user); this.localOnly = false;
}); this.visibility = v;
}); }
}, },
removeVisibleUser(user) { removeVisibleUser(user) {
@@ -320,6 +324,7 @@ export default Vue.extend({
} : null, } : null,
visibility: this.visibility, visibility: this.visibility,
visibleUserIds: this.visibility == 'specified' ? this.visibleUsers.map(u => u.id) : undefined, visibleUserIds: this.visibility == 'specified' ? this.visibleUsers.map(u => u.id) : undefined,
localOnly: this.localOnly,
viaMobile: viaMobile viaMobile: viaMobile
}).then(data => { }).then(data => {
this.$emit('posted'); this.$emit('posted');

View File

@@ -80,6 +80,9 @@
<option value="followers">{{ $t('@.note-visibility.followers') }}</option> <option value="followers">{{ $t('@.note-visibility.followers') }}</option>
<option value="specified">{{ $t('@.note-visibility.specified') }}</option> <option value="specified">{{ $t('@.note-visibility.specified') }}</option>
<option value="private">{{ $t('@.note-visibility.private') }}</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> </ui-select>
</section> </section>
</section> </section>

View File

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

View File

@@ -26,6 +26,13 @@ props:
ja-JP: "モバイル端末から投稿したか否か(自己申告であることに留意)" ja-JP: "モバイル端末から投稿したか否か(自己申告であることに留意)"
en-US: "Whether this note sent via a mobile device" 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: text:
type: "string" type: "string"
optional: true optional: true

View File

@@ -112,7 +112,12 @@ async function init(): Promise<Config> {
Logger.info('Welcome to Misskey!'); Logger.info('Welcome to Misskey!');
Logger.info(`<<< Misskey v${pkg.version} >>>`); 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(); await MachineInfo.show();
EnvironmentInfo.show(); EnvironmentInfo.show();
@@ -135,6 +140,11 @@ async function init(): Promise<Config> {
configLogger.succ('Loaded'); 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) { if (process.platform === 'linux' && !isRoot() && config.port < 1024) {
Logger.error('You need root privileges to listen on port below 1024 on Linux'); Logger.error('You need root privileges to listen on port below 1024 on Linux');
process.exit(1); process.exit(1);

View File

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

View File

@@ -8,7 +8,9 @@ export type TextElementHashtag = {
hashtag: string; 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; if (!(/^\s#[^\s\.,!\?#]+/.test(text) || (isBegin && /^#[^\s\.,!\?#]+/.test(text)))) return null;
const isHead = text.startsWith('#'); const isHead = text.startsWith('#');
const hashtag = text.match(/^\s?#[^\s\.,!\?#]+/)[0]; 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; 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); const match = text.match(/^@[a-z0-9_]+(?:@[a-z0-9\.\-]+[a-z0-9])?/i);
if (!match) return null; if (!match) return null;
if (/[a-zA-Z0-9]$/.test(before)) return null;
const mention = match[0]; const mention = match[0];
const { username, host } = parseAcct(mention.substr(1)); const { username, host } = parseAcct(mention.substr(1));
const canonical = host != null ? `@${username}@${toUnicode(host)}` : mention; const canonical = host != null ? `@${username}@${toUnicode(host)}` : mention;

View File

@@ -8,7 +8,9 @@ export type TextElementQuote = {
quote: string; 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|$)/) || const match = text.match(/^"([\s\S]+?)\n"/) || text.match(/^\n>([\s\S]+?)(\n\n|$)/) ||
(isBegin ? text.match(/^>([\s\S]+?)(\n\n|$)/) : null); (isBegin ? text.match(/^>([\s\S]+?)(\n\n|$)/) : null);

View File

@@ -8,7 +8,9 @@ export type TextElementTitle = {
title: string; 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/); const match = isBegin ? text.match(/^(【|\[)(.+?)(】|])\n/) : text.match(/^\n(【|\[)(.+?)(】|])\n/);
if (!match) return null; if (!match) return null;
return { return {

View File

@@ -8,10 +8,13 @@ export type TextElementUrl = {
url: string; url: string;
}; };
export default function(text: string) { export default function(text: string, before: string) {
const match = text.match(/^https?:\/\/[\w\/:%#@\$&\?!\(\)\[\]~\.=\+\-]+/); const match = text.match(/^https?:\/\/[\w\/:%#@\$&\?!\(\)\[\]~\.,=\+\-]+/);
if (!match) return null; 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 { return {
type: 'url', type: 'url',
content: url, content: url,

View File

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

View File

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

View File

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

View File

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

View File

@@ -35,17 +35,11 @@ export default async function(resolver: Resolver, actor: IRemoteUser, activity:
log(`Creating the (Re)Note: ${uri}`); log(`Creating the (Re)Note: ${uri}`);
//#region Visibility //#region Visibility
let visibility = 'public'; const visibility = getVisibility(activity.to, activity.cc, actor);
let visibleUsers: IUser[] = []; let visibleUsers: IUser[] = [];
if (!note.to.includes('https://www.w3.org/ns/activitystreams#Public')) { if (visibility == 'specified') {
if (note.cc.includes('https://www.w3.org/ns/activitystreams#Public')) { visibleUsers = await Promise.all(note.to.map(uri => resolvePerson(uri)));
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)));
}
} }
//#endergion //#endergion
@@ -57,3 +51,22 @@ export default async function(resolver: Resolver, actor: IRemoteUser, activity:
uri 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, cw: note.summary,
text: text, text: text,
viaMobile: false, viaMobile: false,
localOnly: false,
geo: undefined, geo: undefined,
visibility, visibility,
visibleUsers, visibleUsers,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -75,9 +75,9 @@ handler.on('status', event => {
const parentState = parentStatuses[0].state; const parentState = parentStatuses[0].state;
const stillFailed = parentState == 'failure' || parentState == 'error'; const stillFailed = parentState == 'failure' || parentState == 'error';
if (stillFailed) { if (stillFailed) {
post(`**BUILD STILL FAILED⚠**: ?[${commit.commit.message}](${commit.html_url})`); post(`⚠️**BUILD STILL FAILED**⚠️: ?[${commit.commit.message}](${commit.html_url})`);
} else { } else {
post(`**🚨BUILD FAILED🚨**: →→→?[${commit.commit.message}](${commit.html_url})←←←`); post(`🚨**BUILD FAILED**🚨: →→→?[${commit.commit.message}](${commit.html_url})←←←`);
} }
}); });
break; break;
@@ -87,7 +87,7 @@ handler.on('status', event => {
handler.on('push', event => { handler.on('push', event => {
const ref = event.ref; const ref = event.ref;
switch (ref) { switch (ref) {
case 'refs/heads/master': case 'refs/heads/develop':
const pusher = event.pusher; const pusher = event.pusher;
const compare = event.compare; const compare = event.compare;
const commits: any[] = event.commits; 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'), commits.reverse().map(commit => `・[?[${commit.id.substr(0, 7)}](${commit.url})] ${commit.message.split('\n')[0]}`).join('\n'),
].join('\n')); ].join('\n'));
break; 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); 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 => { handler.on('watch', event => {
const sender = event.sender; const sender = event.sender;
post(`(((⭐️))) Starred by **${sender.login}** (((⭐️)))`, false); post(`(((⭐️))) Starred by **${sender.login}** (((⭐️)))`, false);

View File

@@ -95,6 +95,7 @@ type Option = {
geo?: any; geo?: any;
poll?: any; poll?: any;
viaMobile?: boolean; viaMobile?: boolean;
localOnly?: boolean;
cw?: string; cw?: string;
visibility?: string; visibility?: string;
visibleUsers?: IUser[]; 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.createdAt == null) data.createdAt = new Date();
if (data.visibility == null) data.visibility = 'public'; if (data.visibility == null) data.visibility = 'public';
if (data.viaMobile == null) data.viaMobile = false; if (data.viaMobile == null) data.viaMobile = false;
if (data.localOnly == null) data.localOnly = false;
if (data.visibleUsers) { if (data.visibleUsers) {
data.visibleUsers = erase(null, 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'); 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) { if (data.text) {
data.text = data.text.trim(); 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) { 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) 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) ? renderAnnounce(data.renote.uri ? data.renote.uri : `${config.url}/notes/${data.renote._id}`, note)
: renderCreate(await renderNote(note, false), note); : renderCreate(await renderNote(note, false), note);
@@ -389,6 +403,7 @@ async function insertNote(user: IUser, data: Option, tags: string[], emojis: str
emojis, emojis,
userId: user._id, userId: user._id,
viaMobile: data.viaMobile, viaMobile: data.viaMobile,
localOnly: data.localOnly,
geo: data.geo || null, geo: data.geo || null,
appId: data.app ? data.app._id : null, appId: data.app ? data.app._id : null,
visibility: data.visibility, visibility: data.visibility,

View File

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