Compare commits

...

59 Commits

Author SHA1 Message Date
9e7b6790fd 2.13.0 2018-05-21 03:21:47 +09:00
8fae064156 Merge pull request #1619 from syuilo/l10n_master
New Crowdin translations
2018-05-21 03:21:09 +09:00
8451f4830c New translations ja.yml (English) 2018-05-21 03:20:57 +09:00
deded2bcf7 Merge pull request #1618 from syuilo/l10n_master
New Crowdin translations
2018-05-21 03:11:52 +09:00
51fcaff90e New translations ja.yml (Korean) 2018-05-21 03:11:11 +09:00
ce8794f7dd New translations ja.yml (Polish) 2018-05-21 03:11:09 +09:00
c61abc3327 New translations ja.yml (Chinese Simplified) 2018-05-21 03:11:07 +09:00
2bff683d52 New translations ja.yml (Italian) 2018-05-21 03:11:05 +09:00
4c408c7330 New translations ja.yml (Russian) 2018-05-21 03:11:03 +09:00
4505a80383 New translations ja.yml (English) 2018-05-21 03:11:01 +09:00
ed3e46953d New translations ja.yml (Spanish) 2018-05-21 03:10:58 +09:00
79fd6c202b New translations ja.yml (German) 2018-05-21 03:10:56 +09:00
aef25ef565 New translations ja.yml (French) 2018-05-21 03:10:54 +09:00
a53d786515 投稿の表示スタイルを選択できるように 2018-05-21 03:08:51 +09:00
27b8b81d4e New translations ja.yml (Korean) 2018-05-21 02:21:21 +09:00
369d9d5641 New translations ja.yml (Polish) 2018-05-21 02:21:19 +09:00
56b77d3cf8 New translations ja.yml (Chinese Simplified) 2018-05-21 02:21:17 +09:00
0d2eb2c07c New translations ja.yml (Italian) 2018-05-21 02:21:15 +09:00
5bc1fe1f2c New translations ja.yml (Russian) 2018-05-21 02:21:13 +09:00
83bf229f5b New translations ja.yml (English) 2018-05-21 02:21:11 +09:00
492d550410 New translations ja.yml (Spanish) 2018-05-21 02:21:09 +09:00
22a72d87ea New translations ja.yml (German) 2018-05-21 02:21:08 +09:00
d5ef52ec17 New translations ja.yml (French) 2018-05-21 02:21:06 +09:00
42c811a523 Refactor 2018-05-21 02:13:39 +09:00
51e3c11acb Merge pull request #1617 from syuilo/l10n_master
New Crowdin translations
2018-05-21 00:08:58 +09:00
b9ab18f5a9 New translations ja.yml (English) 2018-05-20 23:30:48 +09:00
00357c2f07 New translations ja.yml (English) 2018-05-20 23:20:36 +09:00
2f756c9988 New translations ja.yml (English) 2018-05-20 23:16:48 +09:00
4c55a19c6d New translations ja.yml (English) 2018-05-20 23:00:53 +09:00
a6eb0971a4 New translations ja.yml (German) 2018-05-20 22:50:55 +09:00
2e25e000de New translations ja.yml (Polish) 2018-05-20 22:40:46 +09:00
e3a15532bf New translations ja.yml (German) 2018-05-20 22:40:44 +09:00
3dcf721c53 New translations ja.yml (Polish) 2018-05-20 22:30:56 +09:00
b20b975935 Fix bug 2018-05-20 20:26:38 +09:00
2e6905c74c Fix bug 2018-05-20 19:51:51 +09:00
8bb97f2e4c Better error reporting 2018-05-20 19:24:54 +09:00
684a8531b6 2.12.0 2018-05-20 18:00:29 +09:00
0b6ee98f05 Merge pull request #1615 from syuilo/l10n_master
New Crowdin translations
2018-05-20 17:59:32 +09:00
a66225c67f New translations ja.yml (Korean) 2018-05-20 17:51:42 +09:00
67f1d76efe New translations ja.yml (Polish) 2018-05-20 17:51:40 +09:00
fdd14c601a New translations ja.yml (Chinese Simplified) 2018-05-20 17:51:38 +09:00
5fb31512c4 New translations ja.yml (Italian) 2018-05-20 17:51:36 +09:00
8ab0581661 New translations ja.yml (Russian) 2018-05-20 17:51:34 +09:00
f71d9adb75 New translations ja.yml (English) 2018-05-20 17:51:33 +09:00
26f44edfd2 New translations ja.yml (Spanish) 2018-05-20 17:51:31 +09:00
71d3265ddd New translations ja.yml (German) 2018-05-20 17:51:29 +09:00
484fe48076 New translations ja.yml (French) 2018-05-20 17:51:27 +09:00
b6f60f3785 Merge pull request #1614 from syuilo/l10n_master
New Crowdin translations
2018-05-20 17:45:22 +09:00
eb1aa1ef47 Improve mobile settings 2018-05-20 17:45:06 +09:00
1f1955490d New translations ja.yml (Korean) 2018-05-20 17:41:22 +09:00
533af40ac6 New translations ja.yml (Polish) 2018-05-20 17:41:20 +09:00
e2f61e36e1 New translations ja.yml (Chinese Simplified) 2018-05-20 17:41:18 +09:00
aeb59f5bb8 New translations ja.yml (Italian) 2018-05-20 17:41:16 +09:00
501bb9638f New translations ja.yml (Russian) 2018-05-20 17:41:15 +09:00
2f96db4e45 New translations ja.yml (English) 2018-05-20 17:41:13 +09:00
c88dba2364 New translations ja.yml (Spanish) 2018-05-20 17:41:11 +09:00
f146d7bcb6 New translations ja.yml (German) 2018-05-20 17:41:09 +09:00
5b4de85926 New translations ja.yml (French) 2018-05-20 17:41:07 +09:00
f6449a7f32 Improve mobile settings 2018-05-20 17:37:30 +09:00
75 changed files with 595 additions and 506 deletions

View File

@ -1,6 +1,6 @@
--- ---
meta: meta:
lang: "日本語" lang: "Deutsch"
divider: "" divider: ""
common: common:
misskey: "Teile alles mit anderen mithilfe von Misskey" misskey: "Teile alles mit anderen mithilfe von Misskey"
@ -143,74 +143,74 @@ common/views/components/stream-indicator.vue:
reconnecting: "Erneut verbinden" reconnecting: "Erneut verbinden"
connected: "Verbindung hergestellt" connected: "Verbindung hergestellt"
common/views/components/twitter-setting.vue: common/views/components/twitter-setting.vue:
description: "お使いのTwitterアカウントをお使いのMisskeyアカウントに接続しておくと、プロフィールでTwitterアカウント情報が表示されるようになったり、Twitterを用いた便利なサインインを利用できるようになります。" description: "Wenn du deinen Twitter-Account mit deinem Misskey-Account verbindest, siehst du deine Twitter Account-Informationen auf deinem Profil und du kannst dich mit Twitter einloggen."
connected-to: "次のTwitterアカウントに接続されています" connected-to: "Du bist mit diesem Twitter-Account verbunden"
detail: "Mehr..." detail: "Mehr..."
reconnect: "Erneut verbinden" reconnect: "Erneut verbinden"
connect: "Mit Twitter verbinden" connect: "Mit Twitter verbinden"
disconnect: "Trennen" disconnect: "Trennen"
common/views/components/uploader.vue: common/views/components/uploader.vue:
waiting: "待機中" waiting: "Warten"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "確認中" fetching: "Laden"
no-broadcasts: "お知らせはありません" no-broadcasts: "Keine Broadcasts"
have-a-nice-day: "良い一日を!" have-a-nice-day: "Schönen Tag!"
next: "" next: "Nächster"
common/views/widgets/donation.vue: common/views/widgets/donation.vue:
title: "寄付のお願い" title: "Spende"
text: "Misskeyの運営にはドメイン、サーバー等のコストが掛かります。Misskeyは広告を掲載したりしないため、収入を皆様からの寄付に頼っています。もしご興味があれば、{}までご連絡ください。ご協力ありがとうございます。" text: "Um Misskey am Laufen zu halten geben wir Geld für Domain, Server usw. aus. Wir bekommen dafür kein Geld und würden uns freuen, wenn du spenden würdest. Wenn du interessiert bist, dann kontaktiere {}. Danke für deine Unterstützung!"
common/views/widgets/photo-stream.vue: common/views/widgets/photo-stream.vue:
title: "フォトストリーム" title: "Fotostream"
no-photos: "写真はありません" no-photos: "Keine Fotos"
common/views/widgets/server.vue: common/views/widgets/server.vue:
title: "サーバー情報" title: "Serverinformationen"
toggle: "表示を切り替え" toggle: "Sicht umschalten"
commons/views/widgets/visibility-chooser.vue: commons/views/widgets/visibility-chooser.vue:
public: "公開" public: "Öffentlich"
home: "ホーム" home: "Home"
home-desc: "ホームタイムラインにのみ公開" home-desc: "Nur an dieser Stelle sichtbar"
followers: "フォロワー" followers: "Follower"
followers-desc: "自分のフォロワーにのみ公開" followers-desc: "Nur für diejenigen sichtbar, die dir folgen"
specified: "ダイレクト" specified: "Direkt"
specified-desc: "指定したユーザーにのみ公開" specified-desc: "Nur für bestimmte Benutzer"
private: "非公開" private: "Privat"
desktop/views/components/activity.chart.vue: desktop/views/components/activity.chart.vue:
total: "Black ... Total" total: "Schwarz ... komplett"
notes: "Blue ... Notes" notes: "Blau ... Hinweise"
replies: "Red ... Replies" replies: "Rot ... Antworten"
renotes: "Green ... Renotes" renotes: "Grün ... Anmerkungen"
desktop/views/components/activity.vue: desktop/views/components/activity.vue:
title: "アクティビティ" title: "Aktivität"
toggle: "表示を切り替え" toggle: "Sichten umschalten"
desktop/views/components/calendar.vue: desktop/views/components/calendar.vue:
title: "{1} {2}" title: "{1} / {2}"
prev: "前の月" prev: "Vorheriger Monat"
next: "次の月" next: "Nächster Monat"
go: "クリックして時間遡行" go: "Klicke zur Navigation"
desktop/views/components/choose-file-from-drive-window.vue: desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "ファイル選択中" choose-file: "Datei auswählen"
upload: "PCからドライブにファイルをアップロード" upload: "Dateien von deinem PC hochladen"
cancel: "キャンセル" cancel: "Abbrechen"
ok: "決定" ok: "OK"
choose-prompt: "ファイルを選択" choose-prompt: "Wähle eine Datei aus"
desktop/views/components/choose-folder-from-drive-window.vue: desktop/views/components/choose-folder-from-drive-window.vue:
cancel: "キャンセル" cancel: "Abbrechen"
ok: "決定" ok: "OK"
choose-prompt: "フォルダを選択" choose-prompt: "Wähle einen Ordner"
desktop/views/components/crop-window.vue: desktop/views/components/crop-window.vue:
skip: "クロップをスキップ" skip: "Zuschneiden überspringen"
cancel: "キャンセル" cancel: "Abbrechen"
ok: "決定" ok: "OK"
desktop/views/components/drive-window.vue: desktop/views/components/drive-window.vue:
used: "使用中" used: "benutzt"
drive: "ドライブ" drive: "Speicher"
desktop/views/components/drive.file.vue: desktop/views/components/drive.file.vue:
avatar: "アイコン" avatar: "Avatar"
banner: "バナー" banner: "Banner"
contextmenu: contextmenu:
rename: "名前を変更" rename: "Umbenennen"
copy-url: "URLをコピー" copy-url: "URL kopieren"
download: "ダウンロード" download: "Download"
else-files: "その他..." else-files: "その他..."
set-as-avatar: "アイコンに設定" set-as-avatar: "アイコンに設定"
set-as-banner: "バナーに設定" set-as-banner: "バナーに設定"
@ -290,26 +290,26 @@ desktop/views/components/home.vue:
post-form: "投稿フォーム" post-form: "投稿フォーム"
messaging: "メッセージ" messaging: "メッセージ"
server: "サーバー情報" server: "サーバー情報"
donation: "寄付のお願い" donation: "Spende"
nav: "ナビゲーション" nav: "Navigation"
tips: "ヒント" tips: "Tipps"
add: "追加" add: "Hinzufügen"
desktop/views/input-dialog.vue: desktop/views/input-dialog.vue:
cancel: "キャンセル" cancel: "Abbrechen"
ok: "決定" ok: "OK"
desktop/views/components/messaging-room-window.vue: desktop/views/components/messaging-room-window.vue:
title: "メッセージ:" title: "Nachrichten:"
desktop/views/components/messaging-window.vue: desktop/views/components/messaging-window.vue:
title: "Nachrichten" title: "Nachrichten"
desktop/views/components/note-detail.vue: desktop/views/components/note-detail.vue:
more: "会話をもっと読み込む" more: "Lade weitere Konversationen"
private: "(この投稿は非公開です)" private: "(Dieser Post ist privat)"
is-renote: "がRenote" is-renote: "がRenote"
location: "位置情報" location: "Ort"
renote: "Renote" renote: "Anmerkung"
add-reaction: "リアクション" add-reaction: "Reaktion hinzufügen"
desktop/views/components/note-detail.sub.vue: desktop/views/components/note-detail.sub.vue:
private: "(この投稿は非公開です)" private: "(Dieser Post ist privat)"
desktop/views/components/notes.note.vue: desktop/views/components/notes.note.vue:
reposted-by: "Auch geteilt von" reposted-by: "Auch geteilt von"
reply: "Antworten" reply: "Antworten"
@ -317,8 +317,8 @@ desktop/views/components/notes.note.vue:
add-reaction: "Eine Reaktion hinzufügen" add-reaction: "Eine Reaktion hinzufügen"
detail: "Zeige Details" detail: "Zeige Details"
desktop/views/components/notes.vue: desktop/views/components/notes.vue:
error: "読み込みに失敗しました。" error: "Laden fehlgeschlagen."
retry: "リトライ" retry: "Erneut versuchen"
desktop/views/components/notifications.vue: desktop/views/components/notifications.vue:
more: "Mehr" more: "Mehr"
empty: "Keine Benachrichtigungen" empty: "Keine Benachrichtigungen"
@ -348,14 +348,14 @@ desktop/views/components/post-form-window.vue:
attaches: "{} Medien hinzugefügt" attaches: "{} Medien hinzugefügt"
uploading-media: "Lade {} Medien hoch" uploading-media: "Lade {} Medien hoch"
desktop/views/components/progress-dialog.vue: desktop/views/components/progress-dialog.vue:
waiting: "待機中" waiting: "Warten"
desktop/views/components/renote-form.vue: desktop/views/components/renote-form.vue:
quote: "Zitieren..." quote: "Zitieren..."
cancel: "Abbrechen" cancel: "Abbrechen"
renote: "Anmerkung" renote: "Anmerkung"
reposting: "しています..." reposting: "Weitersagen..."
success: "Renoteしました" success: "Weitergesagt!"
failure: "Renoteに失敗しました" failure: "Weitersagen fehlgeschlagen"
desktop/views/components/renote-form-window.vue: desktop/views/components/renote-form-window.vue:
title: "この投稿をRenoteしますか" title: "この投稿をRenoteしますか"
desktop/views/components/settings.vue: desktop/views/components/settings.vue:
@ -426,9 +426,6 @@ desktop/views/components/settings.vue:
advanced-settings: "高度な設定" advanced-settings: "高度な設定"
debug-mode: "デバッグモードを有効にする" debug-mode: "デバッグモードを有効にする"
debug-mode-desc: "この設定はブラウザに記憶されます。" debug-mode-desc: "この設定はブラウザに記憶されます。"
use-raw-script: "生のスクリプトを読み込む"
use-raw-script-desc: "圧縮されていない「生の」スクリプトを使用します。サイズが大きいため、読み込みに時間がかかる場合があります。この設定はブラウザに記憶されます。"
source-info: "Misskeyはソースマップも提供しています。"
experimental: "実験的機能を有効にする" experimental: "実験的機能を有効にする"
experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。" experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。"
tools: "ツール" tools: "ツール"
@ -677,8 +674,9 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?" read-all: "すべての通知を既読にしますか?"
mobile/views/pages/settings/settings.profile.vue: mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール" title: "プロフィール"
will-be-published: "これらのプロフィールは公開されます" will-be-published: "公開されます"
name: "名前" name: "名前"
account: "アカウント"
location: "場所" location: "場所"
description: "自己紹介" description: "自己紹介"
birthday: "誕生日" birthday: "誕生日"
@ -703,11 +701,15 @@ mobile/views/pages/settings.vue:
specify-language: "言語を指定" specify-language: "言語を指定"
design: "デザインと表示" design: "デザインと表示"
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"

View File

@ -287,7 +287,7 @@ desktop/views/components/home.vue:
notifications: "Notifications" notifications: "Notifications"
users: "Recommended users" users: "Recommended users"
polls: "Polls" polls: "Polls"
post-form: "投稿フォーム" post-form: "Post form"
messaging: "Messaging" messaging: "Messaging"
server: "Server info" server: "Server info"
donation: "Donation" donation: "Donation"
@ -302,10 +302,10 @@ desktop/views/components/messaging-room-window.vue:
desktop/views/components/messaging-window.vue: desktop/views/components/messaging-window.vue:
title: "Messaging" title: "Messaging"
desktop/views/components/note-detail.vue: desktop/views/components/note-detail.vue:
more: "会話をもっと読み込む" more: "Load more conversations"
private: "(この投稿は非公開です)" private: "(this post is private)"
is-renote: "がRenote" is-renote: "がRenote"
location: "位置情報" location: "Location"
renote: "Renote" renote: "Renote"
add-reaction: "リアクション" add-reaction: "リアクション"
desktop/views/components/note-detail.sub.vue: desktop/views/components/note-detail.sub.vue:
@ -373,11 +373,11 @@ desktop/views/components/settings.vue:
behaviour: "Behavior" behaviour: "Behavior"
fetch-on-scroll: "Fetch on scroll" fetch-on-scroll: "Fetch on scroll"
fetch-on-scroll-desc: "When you scroll down the page automatically fetches additional content." fetch-on-scroll-desc: "When you scroll down the page automatically fetches additional content."
auto-popout: "ウィンドウの自動ポップアウト" auto-popout: "Auto pop-out window"
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" auto-popout-desc: "Pop-out an opened window if possible. This setting is stored in the browser."
advanced: "Advanced settings" advanced: "Advanced settings"
api-via-stream: "ストリームを経由したAPIリクエスト" api-via-stream: "API request via stream"
api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。" api-via-stream-desc: "API request is performed via the WebSocket connection instead of native fetch API (for better performance). This setting is stored in the browser."
display: "Design and display" display: "Design and display"
customize: "Customize Home" customize: "Customize Home"
dark-mode: "Dark Mode" dark-mode: "Dark Mode"
@ -387,28 +387,28 @@ desktop/views/components/settings.vue:
show-reply-target: "Display reply target" show-reply-target: "Display reply target"
show-my-renotes: "Show my renote in the timeline" show-my-renotes: "Show my renote in the timeline"
show-renoted-my-notes: "Show renoted my post in the timeline" show-renoted-my-notes: "Show renoted my post in the timeline"
show-maps: "マップの自動展開" show-maps: "Show the map"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" show-maps-desc: "Show the map of the location attached to the post."
sound: "Sound" sound: "Sound"
enable-sounds: "Enable sound" enable-sounds: "Enable sound"
enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" enable-sounds-desc: "Play a sound when you received a post/message. This setting is stored in the browser."
volume: "Volume" volume: "Volume"
test: "Test" test: "Test"
mobile: "Mobile" mobile: "Mobile"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "Not mark the post as 'from mobile'"
language: "Language" language: "Language"
pick-language: "Select a language" pick-language: "Select a language"
recommended: "Recommended" recommended: "Recommended"
auto: "Auto" auto: "Auto"
specify-language: "Specify the language" specify-language: "Specify the language"
language-desc: "変更はページの再度読み込み後に反映されます。" language-desc: "You need to reload the page for the changes to take effect."
cache: "Cache" cache: "Cache"
clean-cache: "Cleanup" clean-cache: "Cleanup"
cache-warn: "クリーンアップを行うと、ブラウザに記憶されたアカウント情報のキャッシュ、書きかけの投稿・返信・メッセージ、およびその他のデータ(設定情報含む)が削除されます。クリーンアップを行った後はページを再度読み込みする必要があります。" cache-warn: "The cache of account info/posts/replies/messages/settings stored in the browser will be deleted. You need to reload the page after cleaning up."
cache-cleared: "キャッシュを削除しました" cache-cleared: "Cache cleared"
cache-cleared-desc: "Please reload the page." cache-cleared-desc: "Please reload the page."
auto-watch: "Auto watch" auto-watch: "Auto watch"
auto-watch-desc: "リアクションしたり返信したりした投稿に関する通知を自動的に受け取るようにします。" auto-watch-desc: "Receive notifications about the post/reply/reaction automatically."
about: "About Misskey" about: "About Misskey"
operator: "The admin of this instance" operator: "The admin of this instance"
update: "Misskey Update" update: "Misskey Update"
@ -419,18 +419,15 @@ desktop/views/components/settings.vue:
update-settings: "Advanced settings" update-settings: "Advanced settings"
prevent-update: "アップデートを延期する(非推奨)" prevent-update: "アップデートを延期する(非推奨)"
prevent-update-desc: "この設定をオンにしてもアップデートが反映される場合があります。この設定はこのデバイスのみ有効です。" prevent-update-desc: "この設定をオンにしてもアップデートが反映される場合があります。この設定はこのデバイスのみ有効です。"
no-updates: "利用可能な更新はありません" no-updates: "No updates available"
no-updates-desc: "Your Misskey is up to date." no-updates-desc: "Your Misskey is up to date."
update-available: "New version is available!" update-available: "New version is available!"
update-available-desc: "To reload the page and updates are applied." update-available-desc: "To reload the page and updates are applied."
advanced-settings: "Advanced" advanced-settings: "Advanced"
debug-mode: "Enable the debug mode" debug-mode: "Enable the debug mode"
debug-mode-desc: "This setting is stored in the browser." debug-mode-desc: "This setting is stored in the browser."
use-raw-script: "生のスクリプトを読み込む"
use-raw-script-desc: "圧縮されていない「生の」スクリプトを使用します。サイズが大きいため、読み込みに時間がかかる場合があります。この設定はブラウザに記憶されます。"
source-info: "Misskeyはソースマップも提供しています。"
experimental: "Enable experimental features" experimental: "Enable experimental features"
experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。" experimental-desc: "It would make Misskey client unstable. This setting is stored in the browser."
tools: "Tools" tools: "Tools"
task-manager: "Task Manager" task-manager: "Task Manager"
third-parties: "Third-party" third-parties: "Third-party"
@ -453,7 +450,7 @@ desktop/views/components/settings.2fa.vue:
failed: "Failed to setup. please ensure that the token is correct." failed: "Failed to setup. please ensure that the token is correct."
info: "From now on, enter the token that is displayed on your device in addition to your password when signing-in to Misskey." info: "From now on, enter the token that is displayed on your device in addition to your password when signing-in to Misskey."
desktop/views/components/settings.api.vue: desktop/views/components/settings.api.vue:
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。" intro: "To access the API, set this token as the key 'i' of request parameters."
caution: "Please do not show this token to third parties (do not enter it somewhere else other than here) otherwise your account could get compromised." caution: "Please do not show this token to third parties (do not enter it somewhere else other than here) otherwise your account could get compromised."
regeneration-of-token: "In the unlikely event that this token leaks out you can regenerate it." regeneration-of-token: "In the unlikely event that this token leaks out you can regenerate it."
regenerate-token: "Regenerate the token" regenerate-token: "Regenerate the token"
@ -479,9 +476,9 @@ desktop/views/components/settings.profile.vue:
birthday: "Birthday" birthday: "Birthday"
save: "Update profile" save: "Update profile"
desktop/views/components/sub-note-content.vue: desktop/views/components/sub-note-content.vue:
hidden: "(この投稿は非公開です)" hidden: "(this post is private)"
media: "つのメディア" media: " media"
poll: "投票" poll: "Polls"
desktop/views/components/taskmanager.vue: desktop/views/components/taskmanager.vue:
title: "Task Manager" title: "Task Manager"
desktop/views/components/timeline.vue: desktop/views/components/timeline.vue:
@ -520,14 +517,14 @@ desktop/views/components/users-list.vue:
load-more: "More" load-more: "More"
fetching: "Loading…" fetching: "Loading…"
desktop/views/components/users-list-item.vue: desktop/views/components/users-list-item.vue:
followed: "フォローされています" followed: "Follows you"
desktop/views/components/window.vue: desktop/views/components/window.vue:
popout: "ポップアウト" popout: "Popout"
close: "閉じる" close: "Close"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "Misskey Drive" title: "Misskey Drive"
desktop/views/pages/favorites.vue: desktop/views/pages/favorites.vue:
more: "さらに読み込む" more: "Load More"
desktop/views/pages/home-customize.vue: desktop/views/pages/home-customize.vue:
title: "Customize home" title: "Customize home"
desktop/views/pages/note.vue: desktop/views/pages/note.vue:
@ -570,9 +567,9 @@ desktop/views/pages/user/user.profile.vue:
unmute: "Unmute" unmute: "Unmute"
desktop/views/pages/user/user.timeline.vue: desktop/views/pages/user/user.timeline.vue:
default: "Posts" default: "Posts"
with-replies: "投稿と返信" with-replies: "Posts and replies"
with-media: "メディア" with-media: "Media"
empty: "このユーザーはまだ何も投稿していないようです。" empty: "This user has never posted yet."
desktop/views/widgets/messaging.vue: desktop/views/widgets/messaging.vue:
title: "Messaging" title: "Messaging"
desktop/views/widgets/notifications.vue: desktop/views/widgets/notifications.vue:
@ -587,8 +584,8 @@ desktop/views/widgets/post-form.vue:
note: "Post" note: "Post"
placeholder: "What's happening?" placeholder: "What's happening?"
desktop/views/widgets/profile.vue: desktop/views/widgets/profile.vue:
update-banner: "クリックでバナー編集" update-banner: "Click to edit your banner"
update-avatar: "クリックでアバター編集" update-avatar: "Click to edit your avatar"
desktop/views/widgets/trends.vue: desktop/views/widgets/trends.vue:
title: "Trend" title: "Trend"
refresh: "Show others" refresh: "Show others"
@ -676,11 +673,12 @@ mobile/views/pages/notifications.vue:
notifications: "Notifications" notifications: "Notifications"
read-all: "Are you sure you want to mark all unread notifications as read?" read-all: "Are you sure you want to mark all unread notifications as read?"
mobile/views/pages/settings/settings.profile.vue: mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール" title: "Profile"
will-be-published: "これらのプロフィールは公開されます" will-be-published: "公開されます"
name: "名前" name: "Name"
location: "場所" account: "Account"
description: "自己紹介" location: "Location"
description: "Description"
birthday: "Birthday" birthday: "Birthday"
avatar: "Avatar" avatar: "Avatar"
banner: "Banner" banner: "Banner"
@ -697,17 +695,21 @@ mobile/views/pages/selectdrive.vue:
mobile/views/pages/settings.vue: mobile/views/pages/settings.vue:
signed-in-as: "Signed in as {}" signed-in-as: "Signed in as {}"
lang: "Language" lang: "Language"
lang-tip: "変更はページの再読み込み後に反映されます。" lang-tip: "You will need to reload the page for the changes to take effect."
recommended: "Recommended" recommended: "Recommended"
auto: "Auto" auto: "Auto"
specify-language: "Specify the language" specify-language: "Specify the language"
design: "Design and display" design: "Design and display"
dark-mode: "Dark Mode" dark-mode: "Dark Mode"
i-am-under-limited-internet: "I'm under limited internet"
circle-icons: "Use circle icons" circle-icons: "Use circle icons"
timeline: "Timeline" timeline: "Timeline"
show-reply-target: "Show reply target" show-reply-target: "Show reply target"
show-my-renotes: "Show my renotes" show-my-renotes: "Show my renotes"
show-renoted-my-notes: "Show renoted my notes" show-renoted-my-notes: "Show renoted my notes"
post-style: "Post design"
post-style-standard: "Standard"
post-style-smart: "Smart"
behavior: "Behavior" behavior: "Behavior"
fetch-on-scroll: "Fetch on scroll" fetch-on-scroll: "Fetch on scroll"
disable-via-mobile: "Without the \"mobile posts\" flag" disable-via-mobile: "Without the \"mobile posts\" flag"

View File

@ -426,9 +426,6 @@ desktop/views/components/settings.vue:
advanced-settings: "高度な設定" advanced-settings: "高度な設定"
debug-mode: "デバッグモードを有効にする" debug-mode: "デバッグモードを有効にする"
debug-mode-desc: "この設定はブラウザに記憶されます。" debug-mode-desc: "この設定はブラウザに記憶されます。"
use-raw-script: "生のスクリプトを読み込む"
use-raw-script-desc: "圧縮されていない「生の」スクリプトを使用します。サイズが大きいため、読み込みに時間がかかる場合があります。この設定はブラウザに記憶されます。"
source-info: "Misskeyはソースマップも提供しています。"
experimental: "実験的機能を有効にする" experimental: "実験的機能を有効にする"
experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。" experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。"
tools: "ツール" tools: "ツール"
@ -677,8 +674,9 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?" read-all: "すべての通知を既読にしますか?"
mobile/views/pages/settings/settings.profile.vue: mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール" title: "プロフィール"
will-be-published: "これらのプロフィールは公開されます" will-be-published: "公開されます"
name: "名前" name: "名前"
account: "アカウント"
location: "場所" location: "場所"
description: "自己紹介" description: "自己紹介"
birthday: "誕生日" birthday: "誕生日"
@ -703,11 +701,15 @@ mobile/views/pages/settings.vue:
specify-language: "言語を指定" specify-language: "言語を指定"
design: "デザインと表示" design: "デザインと表示"
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"

View File

@ -426,9 +426,6 @@ desktop/views/components/settings.vue:
advanced-settings: "高度な設定" advanced-settings: "高度な設定"
debug-mode: "デバッグモードを有効にする" debug-mode: "デバッグモードを有効にする"
debug-mode-desc: "この設定はブラウザに記憶されます。" debug-mode-desc: "この設定はブラウザに記憶されます。"
use-raw-script: "生のスクリプトを読み込む"
use-raw-script-desc: "圧縮されていない「生の」スクリプトを使用します。サイズが大きいため、読み込みに時間がかかる場合があります。この設定はブラウザに記憶されます。"
source-info: "Misskeyはソースマップも提供しています。"
experimental: "実験的機能を有効にする" experimental: "実験的機能を有効にする"
experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。" experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。"
tools: "ツール" tools: "ツール"
@ -677,8 +674,9 @@ mobile/views/pages/notifications.vue:
read-all: "Êtes vous sûr de vouloir marqués toutes les notifications non-lus en tant que lus?" read-all: "Êtes vous sûr de vouloir marqués toutes les notifications non-lus en tant que lus?"
mobile/views/pages/settings/settings.profile.vue: mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール" title: "プロフィール"
will-be-published: "これらのプロフィールは公開されます" will-be-published: "公開されます"
name: "名前" name: "名前"
account: "アカウント"
location: "場所" location: "場所"
description: "自己紹介" description: "自己紹介"
birthday: "誕生日" birthday: "誕生日"
@ -703,11 +701,15 @@ mobile/views/pages/settings.vue:
specify-language: "言語を指定" specify-language: "言語を指定"
design: "デザインと表示" design: "デザインと表示"
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"

View File

@ -426,9 +426,6 @@ desktop/views/components/settings.vue:
advanced-settings: "高度な設定" advanced-settings: "高度な設定"
debug-mode: "デバッグモードを有効にする" debug-mode: "デバッグモードを有効にする"
debug-mode-desc: "この設定はブラウザに記憶されます。" debug-mode-desc: "この設定はブラウザに記憶されます。"
use-raw-script: "生のスクリプトを読み込む"
use-raw-script-desc: "圧縮されていない「生の」スクリプトを使用します。サイズが大きいため、読み込みに時間がかかる場合があります。この設定はブラウザに記憶されます。"
source-info: "Misskeyはソースマップも提供しています。"
experimental: "実験的機能を有効にする" experimental: "実験的機能を有効にする"
experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。" experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。"
tools: "ツール" tools: "ツール"
@ -677,8 +674,9 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?" read-all: "すべての通知を既読にしますか?"
mobile/views/pages/settings/settings.profile.vue: mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール" title: "プロフィール"
will-be-published: "これらのプロフィールは公開されます" will-be-published: "公開されます"
name: "名前" name: "名前"
account: "アカウント"
location: "場所" location: "場所"
description: "自己紹介" description: "自己紹介"
birthday: "誕生日" birthday: "誕生日"
@ -703,11 +701,15 @@ mobile/views/pages/settings.vue:
specify-language: "言語を指定" specify-language: "言語を指定"
design: "デザインと表示" design: "デザインと表示"
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"

View File

@ -495,9 +495,6 @@ desktop/views/components/settings.vue:
advanced-settings: "高度な設定" advanced-settings: "高度な設定"
debug-mode: "デバッグモードを有効にする" debug-mode: "デバッグモードを有効にする"
debug-mode-desc: "この設定はブラウザに記憶されます。" debug-mode-desc: "この設定はブラウザに記憶されます。"
use-raw-script: "生のスクリプトを読み込む"
use-raw-script-desc: "圧縮されていない「生の」スクリプトを使用します。サイズが大きいため、読み込みに時間がかかる場合があります。この設定はブラウザに記憶されます。"
source-info: "Misskeyはソースマップも提供しています。"
experimental: "実験的機能を有効にする" experimental: "実験的機能を有効にする"
experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。" experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。"
tools: "ツール" tools: "ツール"
@ -808,8 +805,9 @@ mobile/views/pages/notifications.vue:
mobile/views/pages/settings/settings.profile.vue: mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール" title: "プロフィール"
will-be-published: "これらのプロフィールは公開されます" will-be-published: "公開されます"
name: "名前" name: "名前"
account: "アカウント"
location: "場所" location: "場所"
description: "自己紹介" description: "自己紹介"
birthday: "誕生日" birthday: "誕生日"
@ -837,11 +835,15 @@ mobile/views/pages/settings.vue:
specify-language: "言語を指定" specify-language: "言語を指定"
design: "デザインと表示" design: "デザインと表示"
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"

View File

@ -426,9 +426,6 @@ desktop/views/components/settings.vue:
advanced-settings: "高度な設定" advanced-settings: "高度な設定"
debug-mode: "デバッグモードを有効にする" debug-mode: "デバッグモードを有効にする"
debug-mode-desc: "この設定はブラウザに記憶されます。" debug-mode-desc: "この設定はブラウザに記憶されます。"
use-raw-script: "生のスクリプトを読み込む"
use-raw-script-desc: "圧縮されていない「生の」スクリプトを使用します。サイズが大きいため、読み込みに時間がかかる場合があります。この設定はブラウザに記憶されます。"
source-info: "Misskeyはソースマップも提供しています。"
experimental: "実験的機能を有効にする" experimental: "実験的機能を有効にする"
experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。" experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。"
tools: "ツール" tools: "ツール"
@ -677,8 +674,9 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?" read-all: "すべての通知を既読にしますか?"
mobile/views/pages/settings/settings.profile.vue: mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール" title: "プロフィール"
will-be-published: "これらのプロフィールは公開されます" will-be-published: "公開されます"
name: "名前" name: "名前"
account: "アカウント"
location: "場所" location: "場所"
description: "自己紹介" description: "自己紹介"
birthday: "誕生日" birthday: "誕生日"
@ -703,11 +701,15 @@ mobile/views/pages/settings.vue:
specify-language: "言語を指定" specify-language: "言語を指定"
design: "デザインと表示" design: "デザインと表示"
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"

View File

@ -287,7 +287,7 @@ desktop/views/components/home.vue:
notifications: "Powiadomienia" notifications: "Powiadomienia"
users: "Polecani użytkownicy" users: "Polecani użytkownicy"
polls: "Ankiety" polls: "Ankiety"
post-form: "投稿フォーム" post-form: "Formularz tworzenia"
messaging: "Wiadomości" messaging: "Wiadomości"
server: "Informacje o serwerze" server: "Informacje o serwerze"
donation: "Dotacje" donation: "Dotacje"
@ -302,12 +302,12 @@ desktop/views/components/messaging-room-window.vue:
desktop/views/components/messaging-window.vue: desktop/views/components/messaging-window.vue:
title: "Wiadomości" title: "Wiadomości"
desktop/views/components/note-detail.vue: desktop/views/components/note-detail.vue:
more: "会話をもっと読み込む" more: "Załaduj więcej konwersacji"
private: "(この投稿は非公開です)" private: "(ten wpis jest prywatny)"
is-renote: "がRenote" is-renote: "がRenote"
location: "位置情報" location: "Informacje o lokalizacji"
renote: "Renote" renote: "Przeredaguj"
add-reaction: "リアクション" add-reaction: "Dodaj reakcję"
desktop/views/components/note-detail.sub.vue: desktop/views/components/note-detail.sub.vue:
private: "(ten wpis jest prywatny)" private: "(ten wpis jest prywatny)"
desktop/views/components/notes.note.vue: desktop/views/components/notes.note.vue:
@ -375,49 +375,49 @@ desktop/views/components/settings.vue:
fetch-on-scroll-desc: "Po przewinięciu na dół strony automatycznie zostaną załadowane nowe treści." fetch-on-scroll-desc: "Po przewinięciu na dół strony automatycznie zostaną załadowane nowe treści."
auto-popout: "Automatycznie pojawiające się okna" auto-popout: "Automatycznie pojawiające się okna"
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
advanced: "詳細設定" advanced: "Ustawienia zaawansowane"
api-via-stream: "ストリームを経由したAPIリクエスト" api-via-stream: "ストリームを経由したAPIリクエスト"
api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。" api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。"
display: "デザインと表示" display: "Wygląd i wyświetlanie"
customize: "ホームをカスタマイズ" customize: "Dostosuj stronę główną"
dark-mode: "ダークモード" dark-mode: "Tryb ciemny"
circle-icons: "円形のアイコンを使用" circle-icons: "Używaj okrągłych ikon"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "Używaj gradientów na pasku tytułu okna"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "Wyświetlaj formularz tworzenia wpisu w górnej części osi czasu"
show-reply-target: "リプライ先を表示する" show-reply-target: "Pokazuj cel odpowiedzi"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する" show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する"
show-maps: "マップの自動展開" show-maps: "Automatycznie pokazuj mapę"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" show-maps-desc: "Mapa będzie automatycznie rozwijana dla wpisów zawierających informacje o lokalizacji."
sound: "サウンド" sound: "Dźwięk"
enable-sounds: "サウンドを有効にする" enable-sounds: "Włącz dźwięk"
enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" enable-sounds-desc: "Odtwarzaj dźwięk przy wstawianiu wpisów, wysyłaniu lub otrzymywaniu wiadomości. Opcja ta jest zapamiętywana przez przeglądarkę."
volume: "ボリューム" volume: "Głośność"
test: "テスト" test: "Test"
mobile: "モバイル" mobile: "Wersja mobilna"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "Nie oznaczaj wpisów jako „wysłane z telefonu”"
language: "Język" language: "Język"
pick-language: "Wybierz język" pick-language: "Wybierz język"
recommended: "Zalecane" recommended: "Zalecane"
auto: "Automatycznie" auto: "Automatycznie"
specify-language: "Wybierz język" specify-language: "Wybierz język"
language-desc: "変更はページの再度読み込み後に反映されます。" language-desc: "Aby zmiany zostały uwzględnione, odśwież stronę."
cache: "キャッシュ" cache: "Pamięć podręczna"
clean-cache: "Wyczyść" clean-cache: "Wyczyść"
cache-warn: "クリーンアップを行うと、ブラウザに記憶されたアカウント情報のキャッシュ、書きかけの投稿・返信・メッセージ、およびその他のデータ(設定情報含む)が削除されます。クリーンアップを行った後はページを再度読み込みする必要があります。" cache-warn: "クリーンアップを行うと、ブラウザに記憶されたアカウント情報のキャッシュ、書きかけの投稿・返信・メッセージ、およびその他のデータ(設定情報含む)が削除されます。クリーンアップを行った後はページを再度読み込みする必要があります。"
cache-cleared: "キャッシュを削除しました" cache-cleared: "Wyczyszczono pamięć podręczną"
cache-cleared-desc: "ページを再度読み込みしてください。" cache-cleared-desc: "Proszę odświeżyć stronę."
auto-watch: "投稿の自動ウォッチ" auto-watch: "投稿の自動ウォッチ"
auto-watch-desc: "リアクションしたり返信したりした投稿に関する通知を自動的に受け取るようにします。" auto-watch-desc: "リアクションしたり返信したりした投稿に関する通知を自動的に受け取るようにします。"
about: "Misskeyについて" about: "O Misskey"
operator: "このサーバーの運営者" operator: "Administrator instancji"
update: "Misskey Update" update: "Aktualizacja Misskey"
version: "バージョン:" version: "Wersja:"
latest-version: "最新のバージョン:" latest-version: "Najnowsza wersja:"
update-checking: "アップデートを確認中" update-checking: "Sprawdzanie dostępności aktualizacji"
do-update: "アップデートを確認" do-update: "Sprawdź dostępność aktualizacji"
update-settings: "詳細設定" update-settings: "Ustawienia zaawansowane"
prevent-update: "アップデートを延期する(非推奨)" prevent-update: "Unikaj aktualizacji (niezalecane)"
prevent-update-desc: "Nawet jeżeli opcja jest zaznaczona, aktualizacje mogą zostać wykonane. Opcja dotyczy tylko tego urządzenia." prevent-update-desc: "Nawet jeżeli opcja jest zaznaczona, aktualizacje mogą zostać wykonane. Opcja dotyczy tylko tego urządzenia."
no-updates: "Brak dostępnych aktualizacji" no-updates: "Brak dostępnych aktualizacji"
no-updates-desc: "Twój Misskey jest aktualny." no-updates-desc: "Twój Misskey jest aktualny."
@ -426,9 +426,6 @@ desktop/views/components/settings.vue:
advanced-settings: "Ustawienia zaawansowane" advanced-settings: "Ustawienia zaawansowane"
debug-mode: "Włącz tryb debugowania" debug-mode: "Włącz tryb debugowania"
debug-mode-desc: "To ustawienie jest przechowywane w przeglądarce." debug-mode-desc: "To ustawienie jest przechowywane w przeglądarce."
use-raw-script: "生のスクリプトを読み込む"
use-raw-script-desc: "圧縮されていない「生の」スクリプトを使用します。サイズが大きいため、読み込みに時間がかかる場合があります。この設定はブラウザに記憶されます。"
source-info: "Misskeyはソースマップも提供しています。"
experimental: "Włącz eksperymentalne funkcje" experimental: "Włącz eksperymentalne funkcje"
experimental-desc: "Aktywowanie eksperymentalnych funkcji może spowodować niestabilność Misskey. Opcja ta jest przechowywana w przeglądarce." experimental-desc: "Aktywowanie eksperymentalnych funkcji może spowodować niestabilność Misskey. Opcja ta jest przechowywana w przeglądarce."
tools: "Narzędzia" tools: "Narzędzia"
@ -677,8 +674,9 @@ mobile/views/pages/notifications.vue:
read-all: "Czy na pewno chcesz oznaczyć wszystkie powiadomienia jako przeczytane?" read-all: "Czy na pewno chcesz oznaczyć wszystkie powiadomienia jako przeczytane?"
mobile/views/pages/settings/settings.profile.vue: mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール" title: "プロフィール"
will-be-published: "これらのプロフィールは公開されます" will-be-published: "公開されます"
name: "名前" name: "名前"
account: "アカウント"
location: "場所" location: "場所"
description: "自己紹介" description: "自己紹介"
birthday: "誕生日" birthday: "誕生日"
@ -696,34 +694,38 @@ mobile/views/pages/selectdrive.vue:
select-file: "Wybierz plik" select-file: "Wybierz plik"
mobile/views/pages/settings.vue: mobile/views/pages/settings.vue:
signed-in-as: "Zalogowany jako {}" signed-in-as: "Zalogowany jako {}"
lang: "言語" lang: "Język"
lang-tip: "変更はページの再読み込み後に反映されます。" lang-tip: "Aby zmiany zostały uwzględnione, odśwież stronę."
recommended: "推奨" recommended: "Zalecany"
auto: "自動" auto: "Automatycznie"
specify-language: "言語を指定" specify-language: "Wybierz język"
design: "デザインと表示" design: "Wygląd i wyświetlanie"
dark-mode: "ダークモード" dark-mode: "Tryb ciemny"
circle-icons: "円形のアイコンを使用" i-am-under-limited-internet: "Ograniczaj zużycie transferu"
timeline: "タイムライン" circle-icons: "Używaj okrągłych ikon"
show-reply-target: "リプライ先を表示する" timeline: "Oś czasu"
show-reply-target: "Pokazuj cel odpowiedzi"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
behavior: "動作" post-style: "投稿の表示スタイル"
fetch-on-scroll: "スクロールで自動読み込み" post-style-standard: "標準"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" post-style-smart: "スマート"
behavior: "Zachowanie"
fetch-on-scroll: "Automatycznie ładuj po przeciągnięciu w dół"
disable-via-mobile: "Nie oznaczaj wpisów jako „wysłane z telefonu”"
twitter: "Połączenie z Twitterem" twitter: "Połączenie z Twitterem"
twitter-connect: "Twitterアカウントに接続する" twitter-connect: "Połącz z Twitterem"
twitter-reconnect: "再接続する" twitter-reconnect: "Połącz ponownie"
twitter-disconnect: "切断する" twitter-disconnect: "Rozłącz"
update: "Misskey Update" update: "Aktualizacja Misskey"
version: "バージョン:" version: "Wersja:"
latest-version: "最新のバージョン:" latest-version: "Najnowsza wersja:"
update-checking: "アップデートを確認中" update-checking: "Sprawdzanie dostępności aktualizacji"
check-for-updates: "アップデートを確認" check-for-updates: "Sprawdź dostępność aktualizacji"
no-updates: "利用可能な更新はありません" no-updates: "Brak dostępnych aktualizacji"
no-updates-desc: "お使いのMisskeyは最新です。" no-updates-desc: "Twój Misskey jest aktualny."
update-available: "新しいバージョンが利用可能です" update-available: "Dostępna jest nowa wersja"
update-available-desc: "ページを再度読み込みすると更新が適用されます。" update-available-desc: "Odśwież stronę, aby zastosować aktualizację."
settings: "Ustawienia" settings: "Ustawienia"
signout: "Wyloguj" signout: "Wyloguj"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:

View File

@ -426,9 +426,6 @@ desktop/views/components/settings.vue:
advanced-settings: "高度な設定" advanced-settings: "高度な設定"
debug-mode: "デバッグモードを有効にする" debug-mode: "デバッグモードを有効にする"
debug-mode-desc: "この設定はブラウザに記憶されます。" debug-mode-desc: "この設定はブラウザに記憶されます。"
use-raw-script: "生のスクリプトを読み込む"
use-raw-script-desc: "圧縮されていない「生の」スクリプトを使用します。サイズが大きいため、読み込みに時間がかかる場合があります。この設定はブラウザに記憶されます。"
source-info: "Misskeyはソースマップも提供しています。"
experimental: "実験的機能を有効にする" experimental: "実験的機能を有効にする"
experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。" experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。"
tools: "ツール" tools: "ツール"
@ -677,8 +674,9 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?" read-all: "すべての通知を既読にしますか?"
mobile/views/pages/settings/settings.profile.vue: mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール" title: "プロフィール"
will-be-published: "これらのプロフィールは公開されます" will-be-published: "公開されます"
name: "名前" name: "名前"
account: "アカウント"
location: "場所" location: "場所"
description: "自己紹介" description: "自己紹介"
birthday: "誕生日" birthday: "誕生日"
@ -703,11 +701,15 @@ mobile/views/pages/settings.vue:
specify-language: "言語を指定" specify-language: "言語を指定"
design: "デザインと表示" design: "デザインと表示"
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"

View File

@ -426,9 +426,6 @@ desktop/views/components/settings.vue:
advanced-settings: "高度な設定" advanced-settings: "高度な設定"
debug-mode: "デバッグモードを有効にする" debug-mode: "デバッグモードを有効にする"
debug-mode-desc: "この設定はブラウザに記憶されます。" debug-mode-desc: "この設定はブラウザに記憶されます。"
use-raw-script: "生のスクリプトを読み込む"
use-raw-script-desc: "圧縮されていない「生の」スクリプトを使用します。サイズが大きいため、読み込みに時間がかかる場合があります。この設定はブラウザに記憶されます。"
source-info: "Misskeyはソースマップも提供しています。"
experimental: "実験的機能を有効にする" experimental: "実験的機能を有効にする"
experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。" experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。"
tools: "ツール" tools: "ツール"
@ -677,8 +674,9 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?" read-all: "すべての通知を既読にしますか?"
mobile/views/pages/settings/settings.profile.vue: mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール" title: "プロフィール"
will-be-published: "これらのプロフィールは公開されます" will-be-published: "公開されます"
name: "名前" name: "名前"
account: "アカウント"
location: "場所" location: "場所"
description: "自己紹介" description: "自己紹介"
birthday: "誕生日" birthday: "誕生日"
@ -703,11 +701,15 @@ mobile/views/pages/settings.vue:
specify-language: "言語を指定" specify-language: "言語を指定"
design: "デザインと表示" design: "デザインと表示"
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"

View File

@ -1,8 +1,8 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <i@syuilo.com>", "author": "syuilo <i@syuilo.com>",
"version": "2.11.0", "version": "2.13.0",
"clientVersion": "1.0.5516", "clientVersion": "1.0.5576",
"codename": "nighthike", "codename": "nighthike",
"main": "./built/index.js", "main": "./built/index.js",
"private": true, "private": true,
@ -211,6 +211,7 @@
"vue-template-compiler": "2.5.16", "vue-template-compiler": "2.5.16",
"vuedraggable": "2.16.0", "vuedraggable": "2.16.0",
"vuex": "3.0.1", "vuex": "3.0.1",
"vuex-persistedstate": "^2.5.4",
"web-push": "3.3.1", "web-push": "3.3.1",
"webfinger.js": "2.6.6", "webfinger.js": "2.6.6",
"webpack": "4.8.3", "webpack": "4.8.3",

View File

@ -7,7 +7,7 @@ import locale from '../../locales';
export default class Replacer { export default class Replacer {
private lang: string; private lang: string;
public pattern = /%i18n:([a-z0-9_\-\.\/\|\!]+?)%/g; public pattern = /%i18n:([a-z0-9_\-\.\/\|]+?)%/g;
constructor(lang: string) { constructor(lang: string) {
this.lang = lang; this.lang = lang;
@ -56,11 +56,6 @@ export default class Replacer {
public replacement(match, key) { public replacement(match, key) {
let path = null; let path = null;
const shouldEscape = key[0] == '!';
if (shouldEscape) {
key = key.substr(1);
}
if (key.indexOf('|') != -1) { if (key.indexOf('|') != -1) {
path = key.split('|')[0]; path = key.split('|')[0];
key = key.split('|')[1]; key = key.split('|')[1];
@ -68,8 +63,6 @@ export default class Replacer {
const txt = this.get(path, key); const txt = this.get(path, key);
return shouldEscape return txt.replace(/'/g, '\\x27').replace(/"/g, '\\x22');
? txt.replace(/'/g, '\\x27').replace(/"/g, '\\x22')
: txt.replace(/"/g, '&quot;');
} }
} }

View File

@ -29,11 +29,21 @@
if (url.pathname == '/auth') app = 'auth'; if (url.pathname == '/auth') app = 'auth';
//#endregion //#endregion
// Detect the user language //#region Detect the user language
// Note: The default language is Japanese
let lang = navigator.language.split('-')[0]; let lang = navigator.language.split('-')[0];
// The default language is English
if (!LANGS.includes(lang)) lang = 'en'; if (!LANGS.includes(lang)) lang = 'en';
if (localStorage.getItem('lang')) lang = localStorage.getItem('lang');
const vuex = localStorage.getItem('vuex');
if (vuex) {
const data = JSON.parse(vuex);
if (data.device.lang) lang = data.device.lang;
}
const storedLang = localStorage.getItem('lang');
if (storedLang) lang = storedLang;
//#endregion
// Detect the user agent // Detect the user agent
const ua = navigator.userAgent.toLowerCase(); const ua = navigator.userAgent.toLowerCase();
@ -68,13 +78,6 @@
// Script version // Script version
const ver = localStorage.getItem('v') || VERSION; const ver = localStorage.getItem('v') || VERSION;
// Whether in debug mode
const isDebug = localStorage.getItem('debug') == 'true';
// Whether use raw version script
const raw = (localStorage.getItem('useRawScript') == 'true' && isDebug)
|| ENV != 'production';
// Get salt query // Get salt query
const salt = localStorage.getItem('salt') const salt = localStorage.getItem('salt')
? '?salt=' + localStorage.getItem('salt') ? '?salt=' + localStorage.getItem('salt')
@ -84,7 +87,7 @@
// Note: 'async' make it possible to load the script asyncly. // Note: 'async' make it possible to load the script asyncly.
// 'defer' make it possible to run the script when the dom loaded. // 'defer' make it possible to run the script when the dom loaded.
const script = document.createElement('script'); const script = document.createElement('script');
script.setAttribute('src', `/assets/${app}.${ver}.${lang}.${raw ? 'raw' : 'min'}.js${salt}`); script.setAttribute('src', `/assets/${app}.${ver}.${lang}.js${salt}`);
script.setAttribute('async', 'true'); script.setAttribute('async', 'true');
script.setAttribute('defer', 'true'); script.setAttribute('defer', 'true');
head.appendChild(script); head.appendChild(script);

View File

@ -23,7 +23,7 @@ export default async function(mios: MiOS, force = false, silent = false) {
} }
if (!silent) { if (!silent) {
alert('%i18n:!common.update-available%'.replace('{newer}', newer).replace('{current}', current)); alert('%i18n:common.update-available%'.replace('{newer}', newer).replace('{current}', current));
} }
return newer; return newer;

View File

@ -62,7 +62,7 @@ export class HomeStream extends Stream {
// トークンが再生成されたとき // トークンが再生成されたとき
// このままではMisskeyが利用できないので強制的にサインアウトさせる // このままではMisskeyが利用できないので強制的にサインアウトさせる
this.on('my_token_regenerated', () => { this.on('my_token_regenerated', () => {
alert('%i18n:!common.my-token-regenerated%'); alert('%i18n:common.my-token-regenerated%');
os.signout(); os.signout();
}); });
} }

View File

@ -21,10 +21,13 @@ export default Vue.extend({
} }
}, },
computed: { computed: {
lightmode(): boolean {
return this.$store.state.device.lightmode;
},
style(): any { style(): any {
return { return {
backgroundColor: this.user.avatarColor && this.user.avatarColor.length == 3 ? `rgb(${ this.user.avatarColor.join(',') })` : null, backgroundColor: this.user.avatarColor && this.user.avatarColor.length == 3 ? `rgb(${ this.user.avatarColor.join(',') })` : null,
backgroundImage: `url(${ this.user.avatarUrl }?thumbnail)`, backgroundImage: this.lightmode ? null : `url(${ this.user.avatarUrl }?thumbnail)`,
borderRadius: (this as any).clientSettings.circleIcons ? '100%' : null borderRadius: (this as any).clientSettings.circleIcons ? '100%' : null
}; };
} }

View File

@ -8,21 +8,21 @@
<template v-if="network">%fa:check%</template> <template v-if="network">%fa:check%</template>
<template v-if="!network">%fa:times%</template> <template v-if="!network">%fa:times%</template>
</template> </template>
{{ network == null ? '%i18n:!@checking-network%' : '%i18n:!@network%' }}<mk-ellipsis v-if="network == null"/> {{ network == null ? '%i18n:@checking-network%' : '%i18n:@network%' }}<mk-ellipsis v-if="network == null"/>
</p> </p>
<p v-if="network == true" :data-wip="internet == null"> <p v-if="network == true" :data-wip="internet == null">
<template v-if="internet != null"> <template v-if="internet != null">
<template v-if="internet">%fa:check%</template> <template v-if="internet">%fa:check%</template>
<template v-if="!internet">%fa:times%</template> <template v-if="!internet">%fa:times%</template>
</template> </template>
{{ internet == null ? '%i18n:!@checking-internet%' : '%i18n:!@internet%' }}<mk-ellipsis v-if="internet == null"/> {{ internet == null ? '%i18n:@checking-internet%' : '%i18n:@internet%' }}<mk-ellipsis v-if="internet == null"/>
</p> </p>
<p v-if="internet == true" :data-wip="server == null"> <p v-if="internet == true" :data-wip="server == null">
<template v-if="server != null"> <template v-if="server != null">
<template v-if="server">%fa:check%</template> <template v-if="server">%fa:check%</template>
<template v-if="!server">%fa:times%</template> <template v-if="!server">%fa:times%</template>
</template> </template>
{{ server == null ? '%i18n:!@checking-server%' : '%i18n:!@server%' }}<mk-ellipsis v-if="server == null"/> {{ server == null ? '%i18n:@checking-server%' : '%i18n:@server%' }}<mk-ellipsis v-if="server == null"/>
</p> </p>
</div> </div>
<p v-if="!end">%i18n:@finding%<mk-ellipsis/></p> <p v-if="!end">%i18n:@finding%<mk-ellipsis/></p>

View File

@ -3,9 +3,9 @@
<img src="data:image/jpeg;base64,%base64:/assets/error.jpg%" alt=""/> <img src="data:image/jpeg;base64,%base64:/assets/error.jpg%" alt=""/>
<h1>%i18n:@title%</h1> <h1>%i18n:@title%</h1>
<p class="text"> <p class="text">
<span>{{ '%i18n:!@description%'.substr(0, '%i18n:!@description%'.indexOf('{')) }}</span> <span>{{ '%i18n:@description%'.substr(0, '%i18n:@description%'.indexOf('{')) }}</span>
<a @click="reload">{{ '%i18n:!@description%'.match(/\{(.+?)\}/)[1] }}</a> <a @click="reload">{{ '%i18n:@description%'.match(/\{(.+?)\}/)[1] }}</a>
<span>{{ '%i18n:!@description%'.substr('%i18n:!@description%'.indexOf('}') + 1) }}</span> <span>{{ '%i18n:@description%'.substr('%i18n:@description%'.indexOf('}') + 1) }}</span>
</p> </p>
<button v-if="!troubleshooting" @click="troubleshooting = true">%i18n:@troubleshoot%</button> <button v-if="!troubleshooting" @click="troubleshooting = true">%i18n:@troubleshoot%</button>
<x-troubleshooter v-if="troubleshooting"/> <x-troubleshooter v-if="troubleshooting"/>

View File

@ -8,7 +8,7 @@
<p class="empty" v-if="!init && messages.length == 0">%fa:info-circle%%i18n:@empty%</p> <p class="empty" v-if="!init && messages.length == 0">%fa:info-circle%%i18n:@empty%</p>
<p class="no-history" v-if="!init && messages.length > 0 && !existMoreMessages">%fa:flag%%i18n:@no-history%</p> <p class="no-history" v-if="!init && messages.length > 0 && !existMoreMessages">%fa:flag%%i18n:@no-history%</p>
<button class="more" :class="{ fetching: fetchingMoreMessages }" v-if="existMoreMessages" @click="fetchMoreMessages" :disabled="fetchingMoreMessages"> <button class="more" :class="{ fetching: fetchingMoreMessages }" v-if="existMoreMessages" @click="fetchMoreMessages" :disabled="fetchingMoreMessages">
<template v-if="fetchingMoreMessages">%fa:spinner .pulse .fw%</template>{{ fetchingMoreMessages ? '%i18n:!common.loading%' : '%i18n:!@more%' }} <template v-if="fetchingMoreMessages">%fa:spinner .pulse .fw%</template>{{ fetchingMoreMessages ? '%i18n:common.loading%' : '%i18n:@more%' }}
</button> </button>
<template v-for="(message, i) in _messages"> <template v-for="(message, i) in _messages">
<x-message :message="message" :key="message.id"/> <x-message :message="message" :key="message.id"/>
@ -149,9 +149,9 @@ export default Vue.extend({
onMessage(message) { onMessage(message) {
// サウンドを再生する // サウンドを再生する
if ((this as any).os.isEnableSounds) { if (this.$store.state.device.enableSounds) {
const sound = new Audio(`${url}/assets/message.mp3`); const sound = new Audio(`${url}/assets/message.mp3`);
sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5; sound.volume = this.$store.state.device.soundVolume;
sound.play(); sound.play();
} }
@ -172,7 +172,7 @@ export default Vue.extend({
}); });
} else if (message.userId != (this as any).os.i.id) { } else if (message.userId != (this as any).os.i.id) {
// Notify // Notify
this.notify('%i18n:!@new-message%'); this.notify('%i18n:@new-message%');
} }
}, },

View File

@ -162,9 +162,9 @@ export default Vue.extend({
this.o.put(this.myColor, pos); this.o.put(this.myColor, pos);
// サウンドを再生する // サウンドを再生する
if ((this as any).os.isEnableSounds) { if (this.$store.state.device.enableSounds) {
const sound = new Audio(`${url}/assets/othello-put-me.mp3`); const sound = new Audio(`${url}/assets/othello-put-me.mp3`);
sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5; sound.volume = this.$store.state.device.soundVolume;
sound.play(); sound.play();
} }
@ -186,9 +186,9 @@ export default Vue.extend({
this.$forceUpdate(); this.$forceUpdate();
// サウンドを再生する // サウンドを再生する
if ((this as any).os.isEnableSounds && x.color != this.myColor) { if (this.$store.state.device.enableSounds && x.color != this.myColor) {
const sound = new Audio(`${url}/assets/othello-put-you.mp3`); const sound = new Audio(`${url}/assets/othello-put-you.mp3`);
sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5; sound.volume = this.$store.state.device.soundVolume;
sound.play(); sound.play();
} }
}, },

View File

@ -5,7 +5,7 @@
</p> </p>
<ul ref="choices"> <ul ref="choices">
<li v-for="(choice, i) in choices"> <li v-for="(choice, i) in choices">
<input :value="choice" @input="onInput(i, $event)" :placeholder="'%i18n:!@choice-n%'.replace('{}', i + 1)"> <input :value="choice" @input="onInput(i, $event)" :placeholder="'%i18n:@choice-n%'.replace('{}', i + 1)">
<button @click="remove(i)" title="%i18n:@remove%"> <button @click="remove(i)" title="%i18n:@remove%">
%fa:times% %fa:times%
</button> </button>

View File

@ -1,19 +1,19 @@
<template> <template>
<div class="mk-poll" :data-is-voted="isVoted"> <div class="mk-poll" :data-is-voted="isVoted">
<ul> <ul>
<li v-for="choice in poll.choices" :key="choice.id" @click="vote(choice.id)" :class="{ voted: choice.voted }" :title="!isVoted ? '%i18n:!@vote-to%'.replace('{}', choice.text) : ''"> <li v-for="choice in poll.choices" :key="choice.id" @click="vote(choice.id)" :class="{ voted: choice.voted }" :title="!isVoted ? '%i18n:@vote-to%'.replace('{}', choice.text) : ''">
<div class="backdrop" :style="{ 'width': (showResult ? (choice.votes / total * 100) : 0) + '%' }"></div> <div class="backdrop" :style="{ 'width': (showResult ? (choice.votes / total * 100) : 0) + '%' }"></div>
<span> <span>
<template v-if="choice.isVoted">%fa:check%</template> <template v-if="choice.isVoted">%fa:check%</template>
<span>{{ choice.text }}</span> <span>{{ choice.text }}</span>
<span class="votes" v-if="showResult">({{ '%i18n:!@vote-count%'.replace('{}', choice.votes) }})</span> <span class="votes" v-if="showResult">({{ '%i18n:@vote-count%'.replace('{}', choice.votes) }})</span>
</span> </span>
</li> </li>
</ul> </ul>
<p v-if="total > 0"> <p v-if="total > 0">
<span>{{ '%i18n:!@total-users%'.replace('{}', total) }}</span> <span>{{ '%i18n:@total-users%'.replace('{}', total) }}</span>
<span></span> <span></span>
<a v-if="!isVoted" @click="toggleShowResult">{{ showResult ? '%i18n:!@vote%' : '%i18n:!@show-result%' }}</a> <a v-if="!isVoted" @click="toggleShowResult">{{ showResult ? '%i18n:@vote%' : '%i18n:@show-result%' }}</a>
<span v-if="isVoted">%i18n:@voted%</span> <span v-if="isVoted">%i18n:@voted%</span>
</p> </p>
</div> </div>

View File

@ -22,7 +22,7 @@
import Vue from 'vue'; import Vue from 'vue';
import * as anime from 'animejs'; import * as anime from 'animejs';
const placeholder = '%i18n:!@choose-reaction%'; const placeholder = '%i18n:@choose-reaction%';
export default Vue.extend({ export default Vue.extend({
props: ['note', 'source', 'compact', 'cb'], props: ['note', 'source', 'compact', 'cb'],

View File

@ -9,7 +9,7 @@
<label class="token" v-if="user && user.twoFactorEnabled"> <label class="token" v-if="user && user.twoFactorEnabled">
<input v-model="token" type="number" placeholder="%i18n:@token%" required/>%fa:lock% <input v-model="token" type="number" placeholder="%i18n:@token%" required/>%fa:lock%
</label> </label>
<button type="submit" :disabled="signing">{{ signing ? '%i18n:!@signing-in%' : '%i18n:!@signin%' }}</button> <button type="submit" :disabled="signing">{{ signing ? '%i18n:@signing-in%' : '%i18n:@signin%' }}</button>
もしくは <a :href="`${apiUrl}/signin/twitter`">Twitterでログイン</a> もしくは <a :href="`${apiUrl}/signin/twitter`">Twitterでログイン</a>
</form> </form>
</template> </template>

View File

@ -127,7 +127,7 @@ export default Vue.extend({
location.href = '/'; location.href = '/';
}); });
}).catch(() => { }).catch(() => {
alert('%i18n:!@some-error%'); alert('%i18n:@some-error%');
(window as any).grecaptcha.reset(); (window as any).grecaptcha.reset();
this.recaptchaed = false; this.recaptchaed = false;

View File

@ -44,16 +44,16 @@ export default Vue.extend({
const time = this._time; const time = this._time;
const ago = (this.now.getTime() - time.getTime()) / 1000/*ms*/; const ago = (this.now.getTime() - time.getTime()) / 1000/*ms*/;
return ( return (
ago >= 31536000 ? '%i18n:!common.time.years_ago%' .replace('{}', (~~(ago / 31536000)).toString()) : ago >= 31536000 ? '%i18n:common.time.years_ago%' .replace('{}', (~~(ago / 31536000)).toString()) :
ago >= 2592000 ? '%i18n:!common.time.months_ago%' .replace('{}', (~~(ago / 2592000)).toString()) : ago >= 2592000 ? '%i18n:common.time.months_ago%' .replace('{}', (~~(ago / 2592000)).toString()) :
ago >= 604800 ? '%i18n:!common.time.weeks_ago%' .replace('{}', (~~(ago / 604800)).toString()) : ago >= 604800 ? '%i18n:common.time.weeks_ago%' .replace('{}', (~~(ago / 604800)).toString()) :
ago >= 86400 ? '%i18n:!common.time.days_ago%' .replace('{}', (~~(ago / 86400)).toString()) : ago >= 86400 ? '%i18n:common.time.days_ago%' .replace('{}', (~~(ago / 86400)).toString()) :
ago >= 3600 ? '%i18n:!common.time.hours_ago%' .replace('{}', (~~(ago / 3600)).toString()) : ago >= 3600 ? '%i18n:common.time.hours_ago%' .replace('{}', (~~(ago / 3600)).toString()) :
ago >= 60 ? '%i18n:!common.time.minutes_ago%'.replace('{}', (~~(ago / 60)).toString()) : ago >= 60 ? '%i18n:common.time.minutes_ago%'.replace('{}', (~~(ago / 60)).toString()) :
ago >= 10 ? '%i18n:!common.time.seconds_ago%'.replace('{}', (~~(ago % 60)).toString()) : ago >= 10 ? '%i18n:common.time.seconds_ago%'.replace('{}', (~~(ago % 60)).toString()) :
ago >= 0 ? '%i18n:!common.time.just_now%' : ago >= 0 ? '%i18n:common.time.just_now%' :
ago < 0 ? '%i18n:!common.time.future%' : ago < 0 ? '%i18n:common.time.future%' :
'%i18n:!common.time.unknown%'); '%i18n:common.time.unknown%');
} }
}, },
created() { created() {

View File

@ -3,7 +3,7 @@
<p>%i18n:@description%<a :href="`${docsUrl}/link-to-twitter`" target="_blank">%i18n:@detail%</a></p> <p>%i18n:@description%<a :href="`${docsUrl}/link-to-twitter`" target="_blank">%i18n:@detail%</a></p>
<p class="account" v-if="os.i.twitter" :title="`Twitter ID: ${os.i.twitter.userId}`">%i18n:@connected-to%: <a :href="`https://twitter.com/${os.i.twitter.screenName}`" target="_blank">@{{ os.i.twitter.screenName }}</a></p> <p class="account" v-if="os.i.twitter" :title="`Twitter ID: ${os.i.twitter.userId}`">%i18n:@connected-to%: <a :href="`https://twitter.com/${os.i.twitter.screenName}`" target="_blank">@{{ os.i.twitter.screenName }}</a></p>
<p> <p>
<a :href="`${apiUrl}/connect/twitter`" target="_blank" @click.prevent="connect">{{ os.i.twitter ? '%i18n:!@reconnect%' : '%i18n:!@connect%' }}</a> <a :href="`${apiUrl}/connect/twitter`" target="_blank" @click.prevent="connect">{{ os.i.twitter ? '%i18n:@reconnect%' : '%i18n:@connect%' }}</a>
<span v-if="os.i.twitter"> or </span> <span v-if="os.i.twitter"> or </span>
<a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="os.i.twitter" @click.prevent="disconnect">%i18n:@disconnect%</a> <a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="os.i.twitter" @click.prevent="disconnect">%i18n:@disconnect%</a>
</p> </p>

View File

@ -14,7 +14,7 @@
</svg> </svg>
</div> </div>
<p class="fetching" v-if="fetching">%i18n:@fetching%<mk-ellipsis/></p> <p class="fetching" v-if="fetching">%i18n:@fetching%<mk-ellipsis/></p>
<h1 v-if="!fetching">{{ broadcasts.length == 0 ? '%i18n:!@no-broadcasts%' : broadcasts[i].title }}</h1> <h1 v-if="!fetching">{{ broadcasts.length == 0 ? '%i18n:@no-broadcasts%' : broadcasts[i].title }}</h1>
<p v-if="!fetching"> <p v-if="!fetching">
<span v-if="broadcasts.length != 0" v-html="broadcasts[i].text"></span> <span v-if="broadcasts.length != 0" v-html="broadcasts[i].text"></span>
<template v-if="broadcasts.length == 0">%i18n:@have-a-nice-day%</template> <template v-if="broadcasts.length == 0">%i18n:@have-a-nice-day%</template>

View File

@ -3,9 +3,9 @@
<article> <article>
<h1>%fa:heart%%i18n:@title%</h1> <h1>%fa:heart%%i18n:@title%</h1>
<p> <p>
{{ '%i18n:!@text%'.substr(0, '%i18n:!@text%'.indexOf('{')) }} {{ '%i18n:@text%'.substr(0, '%i18n:@text%'.indexOf('{')) }}
<a href="https://syuilo.com">@syuilo</a> <a href="https://syuilo.com">@syuilo</a>
{{ '%i18n:!@text%'.substr('%i18n:!@text%'.indexOf('}') + 1) }} {{ '%i18n:@text%'.substr('%i18n:@text%'.indexOf('}') + 1) }}
</p> </p>
</article> </article>
</div> </div>

View File

@ -8,6 +8,7 @@ declare const _STATS_URL_: string;
declare const _STATUS_URL_: string; declare const _STATUS_URL_: string;
declare const _DEV_URL_: string; declare const _DEV_URL_: string;
declare const _LANG_: string; declare const _LANG_: string;
declare const _LANGS_: string;
declare const _RECAPTCHA_SITEKEY_: string; declare const _RECAPTCHA_SITEKEY_: string;
declare const _SW_PUBLICKEY_: string; declare const _SW_PUBLICKEY_: string;
declare const _THEME_COLOR_: string; declare const _THEME_COLOR_: string;
@ -27,6 +28,7 @@ export const statsUrl = _STATS_URL_;
export const statusUrl = _STATUS_URL_; export const statusUrl = _STATUS_URL_;
export const devUrl = _DEV_URL_; export const devUrl = _DEV_URL_;
export const lang = _LANG_; export const lang = _LANG_;
export const langs = _LANGS_;
export const recaptchaSitekey = _RECAPTCHA_SITEKEY_; export const recaptchaSitekey = _RECAPTCHA_SITEKEY_;
export const swPublickey = _SW_PUBLICKEY_; export const swPublickey = _SW_PUBLICKEY_;
export const themeColor = _THEME_COLOR_; export const themeColor = _THEME_COLOR_;

View File

@ -2,7 +2,7 @@
<div class="mk-calendar" :data-melt="design == 4 || design == 5"> <div class="mk-calendar" :data-melt="design == 4 || design == 5">
<template v-if="design == 0 || design == 1"> <template v-if="design == 0 || design == 1">
<button @click="prev" title="%i18n:@prev%">%fa:chevron-circle-left%</button> <button @click="prev" title="%i18n:@prev%">%fa:chevron-circle-left%</button>
<p class="title">{{ '%i18n:!@title%'.replace('{1}', year).replace('{2}', month) }}</p> <p class="title">{{ '%i18n:@title%'.replace('{1}', year).replace('{2}', month) }}</p>
<button @click="next" title="%i18n:@next%">%fa:chevron-circle-right%</button> <button @click="next" title="%i18n:@next%">%fa:chevron-circle-right%</button>
</template> </template>
@ -21,7 +21,7 @@
:data-is-out-of-range="isOutOfRange(i + 1)" :data-is-out-of-range="isOutOfRange(i + 1)"
:data-is-donichi="isDonichi(i + 1)" :data-is-donichi="isDonichi(i + 1)"
@click="go(i + 1)" @click="go(i + 1)"
:title="isOutOfRange(i + 1) ? null : '%i18n:!@go%'" :title="isOutOfRange(i + 1) ? null : '%i18n:@go%'"
> >
<div>{{ i + 1 }}</div> <div>{{ i + 1 }}</div>
</div> </div>
@ -58,13 +58,13 @@ export default Vue.extend({
month: new Date().getMonth() + 1, month: new Date().getMonth() + 1,
selected: new Date(), selected: new Date(),
weekdayText: [ weekdayText: [
'%i18n:!common.weekday-short.sunday%', '%i18n:common.weekday-short.sunday%',
'%i18n:!common.weekday-short.monday%', '%i18n:common.weekday-short.monday%',
'%i18n:!common.weekday-short.tuesday%', '%i18n:common.weekday-short.tuesday%',
'%i18n:!common.weekday-short.wednesday%', '%i18n:common.weekday-short.wednesday%',
'%i18n:!common.weekday-short.thursday%', '%i18n:common.weekday-short.thursday%',
'%i18n:!common.weekday-short.friday%', '%i18n:common.weekday-short.friday%',
'%i18n:!common.weekday-short.saturday%' '%i18n:common.weekday-short.saturday%'
] ]
}; };
}, },

View File

@ -64,46 +64,46 @@ export default Vue.extend({
this.isContextmenuShowing = true; this.isContextmenuShowing = true;
contextmenu(e, [{ contextmenu(e, [{
type: 'item', type: 'item',
text: '%i18n:!@contextmenu.rename%', text: '%i18n:@contextmenu.rename%',
icon: '%fa:i-cursor%', icon: '%fa:i-cursor%',
onClick: this.rename onClick: this.rename
}, { }, {
type: 'item', type: 'item',
text: '%i18n:!@contextmenu.copy-url%', text: '%i18n:@contextmenu.copy-url%',
icon: '%fa:link%', icon: '%fa:link%',
onClick: this.copyUrl onClick: this.copyUrl
}, { }, {
type: 'link', type: 'link',
href: `${this.file.url}?download`, href: `${this.file.url}?download`,
text: '%i18n:!@contextmenu.download%', text: '%i18n:@contextmenu.download%',
icon: '%fa:download%', icon: '%fa:download%',
}, { }, {
type: 'divider', type: 'divider',
}, { }, {
type: 'item', type: 'item',
text: '%i18n:!common.delete%', text: '%i18n:common.delete%',
icon: '%fa:R trash-alt%', icon: '%fa:R trash-alt%',
onClick: this.deleteFile onClick: this.deleteFile
}, { }, {
type: 'divider', type: 'divider',
}, { }, {
type: 'nest', type: 'nest',
text: '%i18n:!@contextmenu.else-files%', text: '%i18n:@contextmenu.else-files%',
menu: [{ menu: [{
type: 'item', type: 'item',
text: '%i18n:!@contextmenu.set-as-avatar%', text: '%i18n:@contextmenu.set-as-avatar%',
onClick: this.setAsAvatar onClick: this.setAsAvatar
}, { }, {
type: 'item', type: 'item',
text: '%i18n:!@contextmenu.set-as-banner%', text: '%i18n:@contextmenu.set-as-banner%',
onClick: this.setAsBanner onClick: this.setAsBanner
}] }]
}, { }, {
type: 'nest', type: 'nest',
text: '%i18n:!@contextmenu.open-in-app%', text: '%i18n:@contextmenu.open-in-app%',
menu: [{ menu: [{
type: 'item', type: 'item',
text: '%i18n:!@contextmenu.add-app%...', text: '%i18n:@contextmenu.add-app%...',
onClick: this.addApp onClick: this.addApp
}] }]
}], { }], {
@ -141,8 +141,8 @@ export default Vue.extend({
rename() { rename() {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:!@contextmenu.rename-file%', title: '%i18n:@contextmenu.rename-file%',
placeholder: '%i18n:!@contextmenu.input-new-file-name%', placeholder: '%i18n:@contextmenu.input-new-file-name%',
default: this.file.name, default: this.file.name,
allowEmpty: false allowEmpty: false
}).then(name => { }).then(name => {
@ -157,9 +157,9 @@ export default Vue.extend({
copyToClipboard(this.file.url); copyToClipboard(this.file.url);
(this as any).apis.dialog({ (this as any).apis.dialog({
title: '%fa:check%%i18n:@contextmenu.copied%', title: '%fa:check%%i18n:@contextmenu.copied%',
text: '%i18n:!@contextmenu.copied-url-to-clipboard%', text: '%i18n:@contextmenu.copied-url-to-clipboard%',
actions: [{ actions: [{
text: '%i18n:!common.ok%' text: '%i18n:common.ok%'
}] }]
}); });
}, },

View File

@ -54,26 +54,26 @@ export default Vue.extend({
this.isContextmenuShowing = true; this.isContextmenuShowing = true;
contextmenu(e, [{ contextmenu(e, [{
type: 'item', type: 'item',
text: '%i18n:!@contextmenu.move-to-this-folder%', text: '%i18n:@contextmenu.move-to-this-folder%',
icon: '%fa:arrow-right%', icon: '%fa:arrow-right%',
onClick: this.go onClick: this.go
}, { }, {
type: 'item', type: 'item',
text: '%i18n:!@contextmenu.show-in-new-window%', text: '%i18n:@contextmenu.show-in-new-window%',
icon: '%fa:R window-restore%', icon: '%fa:R window-restore%',
onClick: this.newWindow onClick: this.newWindow
}, { }, {
type: 'divider', type: 'divider',
}, { }, {
type: 'item', type: 'item',
text: '%i18n:!@contextmenu.rename%', text: '%i18n:@contextmenu.rename%',
icon: '%fa:i-cursor%', icon: '%fa:i-cursor%',
onClick: this.rename onClick: this.rename
}, { }, {
type: 'divider', type: 'divider',
}, { }, {
type: 'item', type: 'item',
text: '%i18n:!common.delete%', text: '%i18n:common.delete%',
icon: '%fa:R trash-alt%', icon: '%fa:R trash-alt%',
onClick: this.deleteFolder onClick: this.deleteFolder
}], { }], {
@ -159,15 +159,15 @@ export default Vue.extend({
switch (err) { switch (err) {
case 'detected-circular-definition': case 'detected-circular-definition':
(this as any).apis.dialog({ (this as any).apis.dialog({
title: '%fa:exclamation-triangle%%i18n:!@unable-to-process%', title: '%fa:exclamation-triangle%%i18n:@unable-to-process%',
text: '%i18n:!@circular-reference-detected%', text: '%i18n:@circular-reference-detected%',
actions: [{ actions: [{
text: '%i18n:!common.ok%' text: '%i18n:common.ok%'
}] }]
}); });
break; break;
default: default:
alert('%i18n:!@unhandled-error% ' + err); alert('%i18n:@unhandled-error% ' + err);
} }
}); });
} }
@ -199,8 +199,8 @@ export default Vue.extend({
rename() { rename() {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:!@contextmenu.rename-folder%', title: '%i18n:@contextmenu.rename-folder%',
placeholder: '%i18n:!@contextmenu.input-new-folder-name%', placeholder: '%i18n:@contextmenu.input-new-folder-name%',
default: this.folder.name default: this.folder.name
}).then(name => { }).then(name => {
(this as any).api('drive/folders/update', { (this as any).api('drive/folders/update', {

View File

@ -8,7 +8,7 @@
@drop.stop="onDrop" @drop.stop="onDrop"
> >
<template v-if="folder == null">%fa:cloud%</template> <template v-if="folder == null">%fa:cloud%</template>
<span>{{ folder == null ? '%i18n:!@drive%' : folder.name }}</span> <span>{{ folder == null ? '%i18n:@drive%' : folder.name }}</span>
</div> </div>
</template> </template>

View File

@ -138,17 +138,17 @@ export default Vue.extend({
onContextmenu(e) { onContextmenu(e) {
contextmenu(e, [{ contextmenu(e, [{
type: 'item', type: 'item',
text: '%i18n:!@contextmenu.create-folder%', text: '%i18n:@contextmenu.create-folder%',
icon: '%fa:R folder%', icon: '%fa:R folder%',
onClick: this.createFolder onClick: this.createFolder
}, { }, {
type: 'item', type: 'item',
text: '%i18n:!@contextmenu.upload%', text: '%i18n:@contextmenu.upload%',
icon: '%fa:upload%', icon: '%fa:upload%',
onClick: this.selectLocalFile onClick: this.selectLocalFile
}, { }, {
type: 'item', type: 'item',
text: '%i18n:!@contextmenu.url-upload%', text: '%i18n:@contextmenu.url-upload%',
icon: '%fa:cloud-upload-alt%', icon: '%fa:cloud-upload-alt%',
onClick: this.urlUpload onClick: this.urlUpload
}]); }]);
@ -306,15 +306,15 @@ export default Vue.extend({
switch (err) { switch (err) {
case 'detected-circular-definition': case 'detected-circular-definition':
(this as any).apis.dialog({ (this as any).apis.dialog({
title: '%fa:exclamation-triangle%%i18n:!@unable-to-process%', title: '%fa:exclamation-triangle%%i18n:@unable-to-process%',
text: '%i18n:!@circular-reference-detected%', text: '%i18n:@circular-reference-detected%',
actions: [{ actions: [{
text: '%i18n:!common.ok%' text: '%i18n:common.ok%'
}] }]
}); });
break; break;
default: default:
alert('%i18n:!@unhandled-error% ' + err); alert('%i18n:@unhandled-error% ' + err);
} }
}); });
} }
@ -327,8 +327,8 @@ export default Vue.extend({
urlUpload() { urlUpload() {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:!@url-upload%', title: '%i18n:@url-upload%',
placeholder: '%i18n:!@url-of-file%' placeholder: '%i18n:@url-of-file%'
}).then(url => { }).then(url => {
(this as any).api('drive/files/upload_from_url', { (this as any).api('drive/files/upload_from_url', {
url: url, url: url,
@ -337,9 +337,9 @@ export default Vue.extend({
(this as any).apis.dialog({ (this as any).apis.dialog({
title: '%fa:check%%i18n:@url-upload-requested%', title: '%fa:check%%i18n:@url-upload-requested%',
text: '%i18n:!@may-take-time%', text: '%i18n:@may-take-time%',
actions: [{ actions: [{
text: '%i18n:!common.ok%' text: '%i18n:common.ok%'
}] }]
}); });
}); });
@ -347,8 +347,8 @@ export default Vue.extend({
createFolder() { createFolder() {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:!@create-folder%', title: '%i18n:@create-folder%',
placeholder: '%i18n:!@folder-name%' placeholder: '%i18n:@folder-name%'
}).then(name => { }).then(name => {
(this as any).api('drive/folders/create', { (this as any).api('drive/folders/create', {
name: name, name: name,

View File

@ -1,7 +1,7 @@
<template> <template>
<mk-window width="400px" height="550px" @closed="$destroy"> <mk-window width="400px" height="550px" @closed="$destroy">
<span slot="header" :class="$style.header"> <span slot="header" :class="$style.header">
<img :src="`${user.avatarUrl}?thumbnail&size=64`" alt=""/>%i18n:!@followers%.replace('{}', {{ user | userName }}) <img :src="`${user.avatarUrl}?thumbnail&size=64`" alt=""/>%i18n:@followers%.replace('{}', {{ user | userName }})
</span> </span>
<mk-followers :user="user"/> <mk-followers :user="user"/>
</mk-window> </mk-window>

View File

@ -1,7 +1,7 @@
<template> <template>
<mk-window width="400px" height="550px" @closed="$destroy"> <mk-window width="400px" height="550px" @closed="$destroy">
<span slot="header" :class="$style.header"> <span slot="header" :class="$style.header">
<img :src="`${user.avatarUrl}?thumbnail&size=64`" alt=""/>%i18n:!@following%.replace('{}', {{ user | userName }}) <img :src="`${user.avatarUrl}?thumbnail&size=64`" alt=""/>%i18n:@following%.replace('{}', {{ user | userName }})
</span> </span>
<mk-following :user="user"/> <mk-following :user="user"/>
</mk-window> </mk-window>

View File

@ -102,7 +102,7 @@ export default Vue.extend({
computed: { computed: {
home(): any[] { home(): any[] {
return this.$store.state.settings.data.home; return this.$store.state.settings.home;
}, },
left(): any[] { left(): any[] {
return this.home.filter(w => w.place == 'left'); return this.home.filter(w => w.place == 'left');

View File

@ -59,7 +59,7 @@
<template v-else>%fa:reply%</template> <template v-else>%fa:reply%</template>
<p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p> <p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p>
</button> </button>
<button @click="renote" title="%i18n:@renote%> <button @click="renote" title="%i18n:@renote%">
%fa:retweet%<p class="count" v-if="p.renoteCount > 0">{{ p.renoteCount }}</p> %fa:retweet%<p class="count" v-if="p.renoteCount > 0">{{ p.renoteCount }}</p>
</button> </button>
<button :class="{ reacted: p.myReaction != null }" @click="react" ref="reactButton" title="%i18n:@add-reaction%"> <button :class="{ reacted: p.myReaction != null }" @click="react" ref="reactButton" title="%i18n:@add-reaction%">

View File

@ -6,9 +6,9 @@
<div class="renote" v-if="isRenote"> <div class="renote" v-if="isRenote">
<mk-avatar class="avatar" :user="note.user"/> <mk-avatar class="avatar" :user="note.user"/>
%fa:retweet% %fa:retweet%
<span>{{ '%i18n:!@reposted-by%'.substr(0, '%i18n:!@reposted-by%'.indexOf('{')) }}</span> <span>{{ '%i18n:@reposted-by%'.substr(0, '%i18n:@reposted-by%'.indexOf('{')) }}</span>
<a class="name" :href="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</a> <a class="name" :href="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</a>
<span>{{ '%i18n:!@reposted-by%'.substr('%i18n:!@reposted-by%'.indexOf('}') + 1) }}</span> <span>{{ '%i18n:@reposted-by%'.substr('%i18n:@reposted-by%'.indexOf('}') + 1) }}</span>
<mk-time :time="note.createdAt"/> <mk-time :time="note.createdAt"/>
</div> </div>
<article> <article>

View File

@ -145,9 +145,9 @@ export default Vue.extend({
this.notes.unshift(note); this.notes.unshift(note);
// サウンドを再生する // サウンドを再生する
if ((this as any).os.isEnableSounds && !silent) { if (this.$store.state.device.enableSounds && !silent) {
const sound = new Audio(`${url}/assets/post.mp3`); const sound = new Audio(`${url}/assets/post.mp3`);
sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5; sound.volume = this.$store.state.device.soundVolume;
sound.play(); sound.play();
} }

View File

@ -81,7 +81,7 @@
</transition-group> </transition-group>
</div> </div>
<button class="more" :class="{ fetching: fetchingMoreNotifications }" v-if="moreNotifications" @click="fetchMoreNotifications" :disabled="fetchingMoreNotifications"> <button class="more" :class="{ fetching: fetchingMoreNotifications }" v-if="moreNotifications" @click="fetchMoreNotifications" :disabled="fetchingMoreNotifications">
<template v-if="fetchingMoreNotifications">%fa:spinner .pulse .fw%</template>{{ fetchingMoreNotifications ? '%i18n:!common.loading%' : '%i18n:!@more%' }} <template v-if="fetchingMoreNotifications">%fa:spinner .pulse .fw%</template>{{ fetchingMoreNotifications ? '%i18n:common.loading%' : '%i18n:@more%' }}
</button> </button>
<p class="empty" v-if="notifications.length == 0 && !fetching">%i18n:@empty%</p> <p class="empty" v-if="notifications.length == 0 && !fetching">%i18n:@empty%</p>
<p class="loading" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p> <p class="loading" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>

View File

@ -4,8 +4,8 @@
<span :class="$style.icon" v-if="geo">%fa:map-marker-alt%</span> <span :class="$style.icon" v-if="geo">%fa:map-marker-alt%</span>
<span v-if="!reply">%i18n:@note%</span> <span v-if="!reply">%i18n:@note%</span>
<span v-if="reply">%i18n:@reply%</span> <span v-if="reply">%i18n:@reply%</span>
<span :class="$style.count" v-if="media.length != 0">{{ '%i18n:!@attaches%'.replace('{}', media.length) }}</span> <span :class="$style.count" v-if="media.length != 0">{{ '%i18n:@attaches%'.replace('{}', media.length) }}</span>
<span :class="$style.count" v-if="uploadings.length != 0">{{ '%i18n:!@uploading-media%'.replace('{}', uploadings.length) }}<mk-ellipsis/></span> <span :class="$style.count" v-if="uploadings.length != 0">{{ '%i18n:@uploading-media%'.replace('{}', uploadings.length) }}<mk-ellipsis/></span>
</span> </span>
<mk-note-preview v-if="reply" :class="$style.notePreview" :note="reply"/> <mk-note-preview v-if="reply" :class="$style.notePreview" :note="reply"/>

View File

@ -37,7 +37,7 @@
<button class="visibility" title="公開範囲" @click="setVisibility" ref="visibilityButton">%fa:lock%</button> <button class="visibility" title="公開範囲" @click="setVisibility" ref="visibilityButton">%fa:lock%</button>
<p class="text-count" :class="{ over: text.length > 1000 }">{{ 1000 - text.length }}</p> <p class="text-count" :class="{ over: text.length > 1000 }">{{ 1000 - text.length }}</p>
<button :class="{ posting }" class="submit" :disabled="!canPost" @click="post"> <button :class="{ posting }" class="submit" :disabled="!canPost" @click="post">
{{ posting ? '%i18n:!@posting%' : submitText }}<mk-ellipsis v-if="posting"/> {{ posting ? '%i18n:@posting%' : submitText }}<mk-ellipsis v-if="posting"/>
</button> </button>
<input ref="file" type="file" accept="image/*" multiple="multiple" tabindex="-1" @change="onChangeFile"/> <input ref="file" type="file" accept="image/*" multiple="multiple" tabindex="-1" @change="onChangeFile"/>
<div class="dropzone" v-if="draghover"></div> <div class="dropzone" v-if="draghover"></div>
@ -86,18 +86,18 @@ export default Vue.extend({
placeholder(): string { placeholder(): string {
return this.renote return this.renote
? '%i18n:!@quote-placeholder%' ? '%i18n:@quote-placeholder%'
: this.reply : this.reply
? '%i18n:!@reply-placeholder%' ? '%i18n:@reply-placeholder%'
: '%i18n:!@note-placeholder%'; : '%i18n:@note-placeholder%';
}, },
submitText(): string { submitText(): string {
return this.renote return this.renote
? '%i18n:!@renote%' ? '%i18n:@renote%'
: this.reply : this.reply
? '%i18n:!@reply%' ? '%i18n:@reply%'
: '%i18n:!@note%'; : '%i18n:@note%';
}, },
canPost(): boolean { canPost(): boolean {
@ -304,16 +304,16 @@ export default Vue.extend({
this.deleteDraft(); this.deleteDraft();
this.$emit('posted'); this.$emit('posted');
(this as any).apis.notify(this.renote (this as any).apis.notify(this.renote
? '%i18n:!@reposted%' ? '%i18n:@reposted%'
: this.reply : this.reply
? '%i18n:!@replied%' ? '%i18n:@replied%'
: '%i18n:!@posted%'); : '%i18n:@posted%');
}).catch(err => { }).catch(err => {
(this as any).apis.notify(this.renote (this as any).apis.notify(this.renote
? '%i18n:!@renote-failed%' ? '%i18n:@renote-failed%'
: this.reply : this.reply
? '%i18n:!@reply-failed%' ? '%i18n:@reply-failed%'
: '%i18n:!@note-failed%'); : '%i18n:@note-failed%');
}).then(() => { }).then(() => {
this.posting = false; this.posting = false;
}); });

View File

@ -5,7 +5,7 @@
<footer> <footer>
<a class="quote" v-if="!quote" @click="onQuote">%i18n:@quote%</a> <a class="quote" v-if="!quote" @click="onQuote">%i18n:@quote%</a>
<button class="ui cancel" @click="cancel">%i18n:@cancel%</button> <button class="ui cancel" @click="cancel">%i18n:@cancel%</button>
<button class="ui primary ok" @click="ok" :disabled="wait">{{ wait ? '%i18n:!@reposting%' : '%i18n:!@renote%' }}</button> <button class="ui primary ok" @click="ok" :disabled="wait">{{ wait ? '%i18n:@reposting%' : '%i18n:@renote%' }}</button>
</footer> </footer>
</template> </template>
<template v-if="quote"> <template v-if="quote">
@ -32,9 +32,9 @@ export default Vue.extend({
renoteId: this.note.id renoteId: this.note.id
}).then(data => { }).then(data => {
this.$emit('posted'); this.$emit('posted');
(this as any).apis.notify('%i18n:!@success%'); (this as any).apis.notify('%i18n:@success%');
}).catch(err => { }).catch(err => {
(this as any).apis.notify('%i18n:!@failure%'); (this as any).apis.notify('%i18n:@failure%');
}).then(() => { }).then(() => {
this.wait = false; this.wait = false;
}); });

View File

@ -34,7 +34,7 @@ export default Vue.extend({
methods: { methods: {
register() { register() {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:!@enter-password%', title: '%i18n:@enter-password%',
type: 'password' type: 'password'
}).then(password => { }).then(password => {
(this as any).api('i/2fa/register', { (this as any).api('i/2fa/register', {
@ -47,13 +47,13 @@ export default Vue.extend({
unregister() { unregister() {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:!@enter-password%', title: '%i18n:@enter-password%',
type: 'password' type: 'password'
}).then(password => { }).then(password => {
(this as any).api('i/2fa/unregister', { (this as any).api('i/2fa/unregister', {
password: password password: password
}).then(() => { }).then(() => {
(this as any).apis.notify('%i18n:!@unregistered%'); (this as any).apis.notify('%i18n:@unregistered%');
(this as any).os.i.twoFactorEnabled = false; (this as any).os.i.twoFactorEnabled = false;
}); });
}); });
@ -63,10 +63,10 @@ export default Vue.extend({
(this as any).api('i/2fa/done', { (this as any).api('i/2fa/done', {
token: this.token token: this.token
}).then(() => { }).then(() => {
(this as any).apis.notify('%i18n:!@success%'); (this as any).apis.notify('%i18n:@success%');
(this as any).os.i.twoFactorEnabled = true; (this as any).os.i.twoFactorEnabled = true;
}).catch(() => { }).catch(() => {
(this as any).apis.notify('%i18n:!@failed%'); (this as any).apis.notify('%i18n:@failed%');
}); });
} }
} }

View File

@ -15,7 +15,7 @@ export default Vue.extend({
methods: { methods: {
regenerateToken() { regenerateToken() {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:!@enter-password%', title: '%i18n:@enter-password%',
type: 'password' type: 'password'
}).then(password => { }).then(password => {
(this as any).api('i/regenerate_token', { (this as any).api('i/regenerate_token', {

View File

@ -11,21 +11,21 @@ export default Vue.extend({
methods: { methods: {
reset() { reset() {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:!@enter-current-password%', title: '%i18n:@enter-current-password%',
type: 'password' type: 'password'
}).then(currentPassword => { }).then(currentPassword => {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:!@enter-new-password%', title: '%i18n:@enter-new-password%',
type: 'password' type: 'password'
}).then(newPassword => { }).then(newPassword => {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:!@enter-new-password-again%', title: '%i18n:@enter-new-password-again%',
type: 'password' type: 'password'
}).then(newPassword2 => { }).then(newPassword2 => {
if (newPassword !== newPassword2) { if (newPassword !== newPassword2) {
(this as any).apis.dialog({ (this as any).apis.dialog({
title: null, title: null,
text: '%i18n:!@not-match%', text: '%i18n:@not-match%',
actions: [{ actions: [{
text: 'OK' text: 'OK'
}] }]
@ -36,7 +36,7 @@ export default Vue.extend({
currentPasword: currentPassword, currentPasword: currentPassword,
newPassword: newPassword newPassword: newPassword
}).then(() => { }).then(() => {
(this as any).apis.notify('%i18n:!@changed%'); (this as any).apis.notify('%i18n:@changed%');
}); });
}); });
}); });

View File

@ -62,8 +62,10 @@
<el-slider <el-slider
v-model="soundVolume" v-model="soundVolume"
:show-input="true" :show-input="true"
:format-tooltip="v => `${v}%`" :format-tooltip="v => `${v * 100}%`"
:disabled="!enableSounds" :disabled="!enableSounds"
:max="1"
:step="0.1"
/> />
<button class="ui button" @click="soundTest">%fa:volume-up% %i18n:@test%</button> <button class="ui button" @click="soundTest">%fa:volume-up% %i18n:@test%</button>
</section> </section>
@ -77,14 +79,10 @@
<h1>%i18n:@language%</h1> <h1>%i18n:@language%</h1>
<el-select v-model="lang" placeholder="%i18n:@pick-language%"> <el-select v-model="lang" placeholder="%i18n:@pick-language%">
<el-option-group label="%i18n:@recommended%"> <el-option-group label="%i18n:@recommended%">
<el-option label="%i18n:@auto%" value=""/> <el-option label="%i18n:@auto%" :value="null"/>
</el-option-group> </el-option-group>
<el-option-group label="%i18n:@specify-language%"> <el-option-group label="%i18n:@specify-language%">
<el-option label="日本語" value="ja"/> <el-option v-for="x in langs" :label="x[1]" :value="x[0]" :key="x[0]"/>
<el-option label="English" value="en"/>
<el-option label="Français" value="fr"/>
<el-option label="Polski" value="pl"/>
<el-option label="Deutsch" value="de"/>
</el-option-group> </el-option-group>
</el-select> </el-select>
<div class="none ui info"> <div class="none ui info">
@ -178,15 +176,7 @@
<mk-switch v-model="debug" text="%i18n:@debug-mode%"> <mk-switch v-model="debug" text="%i18n:@debug-mode%">
<span>%i18n:@debug-mode-desc%</span> <span>%i18n:@debug-mode-desc%</span>
</mk-switch> </mk-switch>
<template v-if="debug"> <mk-switch v-model="enableExperimentalFeatures" text="%i18n:@experimental%">
<mk-switch v-model="useRawScript" text="%i18n:@use-raw-script%">
<span>%i18n:@use-raw-script-desc%</span>
</mk-switch>
<div class="none ui info">
<p>%fa:info-circle%%i18n:@source-info%</p>
</div>
</template>
<mk-switch v-model="enableExperimental" text="%i18n:@experimental%">
<span>%i18n:@experimental-desc%</span> <span>%i18n:@experimental-desc%</span>
</mk-switch> </mk-switch>
<details v-if="debug"> <details v-if="debug">
@ -214,7 +204,7 @@ import XApi from './settings.api.vue';
import XApps from './settings.apps.vue'; import XApps from './settings.apps.vue';
import XSignins from './settings.signins.vue'; import XSignins from './settings.signins.vue';
import XDrive from './settings.drive.vue'; import XDrive from './settings.drive.vue';
import { url, docsUrl, license, lang, version } from '../../../config'; import { url, docsUrl, license, lang, langs, version } from '../../../config';
import checkForUpdate from '../../../common/scripts/check-for-update'; import checkForUpdate from '../../../common/scripts/check-for-update';
import MkTaskManager from './taskmanager.vue'; import MkTaskManager from './taskmanager.vue';
@ -235,55 +225,60 @@ export default Vue.extend({
meta: null, meta: null,
license, license,
version, version,
langs,
latestVersion: undefined, latestVersion: undefined,
checkingForUpdate: false, checkingForUpdate: false,
darkmode: localStorage.getItem('darkmode') == 'true', darkmode: localStorage.getItem('darkmode') == 'true'
enableSounds: localStorage.getItem('enableSounds') == 'true',
autoPopout: localStorage.getItem('autoPopout') == 'true',
apiViaStream: localStorage.getItem('apiViaStream') ? localStorage.getItem('apiViaStream') == 'true' : true,
soundVolume: localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) : 50,
lang: localStorage.getItem('lang') || '',
preventUpdate: localStorage.getItem('preventUpdate') == 'true',
debug: localStorage.getItem('debug') == 'true',
useRawScript: localStorage.getItem('useRawScript') == 'true',
enableExperimental: localStorage.getItem('enableExperimental') == 'true'
}; };
}, },
computed: { computed: {
licenseUrl(): string { licenseUrl(): string {
return `${docsUrl}/${lang}/license`; return `${docsUrl}/${lang}/license`;
},
apiViaStream: {
get() { return this.$store.state.device.apiViaStream; },
set(value) { this.$store.commit('device/set', { key: 'apiViaStream', value }); }
},
autoPopout: {
get() { return this.$store.state.device.autoPopout; },
set(value) { this.$store.commit('device/set', { key: 'autoPopout', value }); }
},
enableSounds: {
get() { return this.$store.state.device.enableSounds; },
set(value) { this.$store.commit('device/set', { key: 'enableSounds', value }); }
},
soundVolume: {
get() { return this.$store.state.device.soundVolume; },
set(value) { this.$store.commit('device/set', { key: 'soundVolume', value }); }
},
lang: {
get() { return this.$store.state.device.lang; },
set(value) { this.$store.commit('device/set', { key: 'lang', value }); }
},
preventUpdate: {
get() { return this.$store.state.device.preventUpdate; },
set(value) { this.$store.commit('device/set', { key: 'preventUpdate', value }); }
},
debug: {
get() { return this.$store.state.device.debug; },
set(value) { this.$store.commit('device/set', { key: 'debug', value }); }
},
enableExperimentalFeatures: {
get() { return this.$store.state.device.enableExperimentalFeatures; },
set(value) { this.$store.commit('device/set', { key: 'enableExperimentalFeatures', value }); }
} }
}, },
watch: { watch: {
autoPopout() {
localStorage.setItem('autoPopout', this.autoPopout ? 'true' : 'false');
},
apiViaStream() {
localStorage.setItem('apiViaStream', this.apiViaStream ? 'true' : 'false');
},
darkmode() { darkmode() {
(this as any)._updateDarkmode_(this.darkmode); (this as any)._updateDarkmode_(this.darkmode);
},
enableSounds() {
localStorage.setItem('enableSounds', this.enableSounds ? 'true' : 'false');
},
soundVolume() {
localStorage.setItem('soundVolume', this.soundVolume.toString());
},
lang() {
localStorage.setItem('lang', this.lang);
},
preventUpdate() {
localStorage.setItem('preventUpdate', this.preventUpdate ? 'true' : 'false');
},
debug() {
localStorage.setItem('debug', this.debug ? 'true' : 'false');
},
useRawScript() {
localStorage.setItem('useRawScript', this.useRawScript ? 'true' : 'false');
},
enableExperimental() {
localStorage.setItem('enableExperimental', this.enableExperimental ? 'true' : 'false');
} }
}, },
created() { created() {
@ -371,13 +366,13 @@ export default Vue.extend({
this.latestVersion = newer; this.latestVersion = newer;
if (newer == null) { if (newer == null) {
(this as any).apis.dialog({ (this as any).apis.dialog({
title: '%i18n:!@no-updates%', title: '%i18n:@no-updates%',
text: '%i18n:!@no-updates-desc%' text: '%i18n:@no-updates-desc%'
}); });
} else { } else {
(this as any).apis.dialog({ (this as any).apis.dialog({
title: '%i18n:!@update-available%', title: '%i18n:@update-available%',
text: '%i18n:!@update-available-desc%' text: '%i18n:@update-available-desc%'
}); });
} }
}); });
@ -385,13 +380,13 @@ export default Vue.extend({
clean() { clean() {
localStorage.clear(); localStorage.clear();
(this as any).apis.dialog({ (this as any).apis.dialog({
title: '%i18n:!@cache-cleared%', title: '%i18n:@cache-cleared%',
text: '%i18n:!@caache-cleared-desc%' text: '%i18n:@caache-cleared-desc%'
}); });
}, },
soundTest() { soundTest() {
const sound = new Audio(`${url}/assets/message.mp3`); const sound = new Audio(`${url}/assets/message.mp3`);
sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5; sound.volume = this.$store.state.device.soundVolume;
sound.play(); sound.play();
} }
} }

View File

@ -95,7 +95,7 @@ export default Vue.extend({
}, },
created() { created() {
if (localStorage.getItem('autoPopout') == 'true' && this.popoutUrl) { if (this.$store.state.device.autoPopout && this.popoutUrl) {
this.popout(); this.popout();
this.preventMount = true; this.preventMount = true;
} else { } else {

View File

@ -29,7 +29,7 @@ export default Vue.extend({
} }
}, },
mounted() { mounted() {
document.title = '%i18n:!@title%'; document.title = '%i18n:@title%';
}, },
methods: { methods: {
onSelected(file) { onSelected(file) {

View File

@ -113,7 +113,7 @@ html.setAttribute('lang', lang);
const head = document.getElementsByTagName('head')[0]; const head = document.getElementsByTagName('head')[0];
const meta = document.createElement('meta'); const meta = document.createElement('meta');
meta.setAttribute('name', 'description'); meta.setAttribute('name', 'description');
meta.setAttribute('content', '%i18n:!common.misskey%'); meta.setAttribute('content', '%i18n:common.misskey%');
head.appendChild(meta); head.appendChild(meta);
//#endregion //#endregion
@ -147,7 +147,7 @@ export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API)
os, os,
api: os.api, api: os.api,
apis: os.apis, apis: os.apis,
clientSettings: os.store.state.settings.data clientSettings: os.store.state.settings
}; };
} }
}); });
@ -173,7 +173,7 @@ export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API)
} }
//#region 更新チェック //#region 更新チェック
const preventUpdate = localStorage.getItem('preventUpdate') == 'true'; const preventUpdate = os.store.state.device.preventUpdate;
if (!preventUpdate) { if (!preventUpdate) {
setTimeout(() => { setTimeout(() => {
checkForUpdate(os); checkForUpdate(os);

View File

@ -98,14 +98,7 @@ export default class MiOS extends EventEmitter {
* Whether is debug mode * Whether is debug mode
*/ */
public get debug() { public get debug() {
return localStorage.getItem('debug') == 'true'; return this.store ? this.store.state.device.debug : false;
}
/**
* Whether enable sounds
*/
public get isEnableSounds() {
return localStorage.getItem('enableSounds') == 'true';
} }
public store: ReturnType<typeof initStore>; public store: ReturnType<typeof initStore>;
@ -435,12 +428,8 @@ export default class MiOS extends EventEmitter {
}); });
}); });
// Whether use raw version script
const raw = (localStorage.getItem('useRawScript') == 'true' && this.debug)
|| process.env.NODE_ENV != 'production';
// The path of service worker script // The path of service worker script
const sw = `/sw.${version}.${lang}.${raw ? 'raw' : 'min'}.js`; const sw = `/sw.${version}.${lang}.js`;
// Register service worker // Register service worker
navigator.serviceWorker.register(sw).then(registration => { navigator.serviceWorker.register(sw).then(registration => {
@ -471,8 +460,7 @@ export default class MiOS extends EventEmitter {
}; };
const promise = new Promise((resolve, reject) => { const promise = new Promise((resolve, reject) => {
const viaStream = this.stream && this.stream.hasConnection && const viaStream = this.stream && this.stream.hasConnection && this.store.state.device.apiViaStream;
(localStorage.getItem('apiViaStream') ? localStorage.getItem('apiViaStream') == 'true' : true);
if (viaStream) { if (viaStream) {
const stream = this.stream.borrow(); const stream = this.stream.borrow();

View File

@ -5,7 +5,7 @@
import Vue from 'vue'; import Vue from 'vue';
import VueRouter from 'vue-router'; import VueRouter from 'vue-router';
import { MdCard, MdButton, MdField, MdMenu, MdList, MdSwitch, MdSubheader, MdDialog, MdDialogAlert } from 'vue-material/dist/components'; import { MdCard, MdButton, MdField, MdMenu, MdList, MdSwitch, MdSubheader, MdDialog, MdDialogAlert, MdRadio } from 'vue-material/dist/components';
import 'vue-material/dist/vue-material.min.css'; import 'vue-material/dist/vue-material.min.css';
import 'vue-material/dist/theme/default.css'; import 'vue-material/dist/theme/default.css';
@ -48,6 +48,7 @@ Vue.use(MdSwitch);
Vue.use(MdSubheader); Vue.use(MdSubheader);
Vue.use(MdDialog); Vue.use(MdDialog);
Vue.use(MdDialogAlert); Vue.use(MdDialogAlert);
Vue.use(MdRadio);
/** /**
* init * init

View File

@ -32,7 +32,7 @@
<div class="files" v-if="files.length > 0"> <div class="files" v-if="files.length > 0">
<x-file v-for="file in files" :key="file.id" :file="file"/> <x-file v-for="file in files" :key="file.id" :file="file"/>
<button class="more" v-if="moreFiles" @click="fetchMoreFiles"> <button class="more" v-if="moreFiles" @click="fetchMoreFiles">
{{ fetchingMoreFiles ? '%i18n:!common.loading%' : '%i18n:!@load-more%' }} {{ fetchingMoreFiles ? '%i18n:common.loading%' : '%i18n:@load-more%' }}
</button> </button>
</div> </div>
<div class="empty" v-if="files.length == 0 && folders.length == 0 && !fetching"> <div class="empty" v-if="files.length == 0 && folders.length == 0 && !fetching">

View File

@ -7,7 +7,7 @@
<template v-if="!wait && user.isFollowing">%fa:minus%</template> <template v-if="!wait && user.isFollowing">%fa:minus%</template>
<template v-if="!wait && !user.isFollowing">%fa:plus%</template> <template v-if="!wait && !user.isFollowing">%fa:plus%</template>
<template v-if="wait">%fa:spinner .pulse .fw%</template> <template v-if="wait">%fa:spinner .pulse .fw%</template>
{{ user.isFollowing ? '%i18n:!@unfollow%' : '%i18n:!@follow%' }} {{ user.isFollowing ? '%i18n:@unfollow%' : '%i18n:@follow%' }}
</button> </button>
</template> </template>

View File

@ -16,10 +16,13 @@ export default Vue.extend({
} }
}, },
computed: { computed: {
lightmode(): boolean {
return this.$store.state.device.lightmode;
},
style(): any { style(): any {
return { return {
'background-color': this.image.properties.avgColor && this.image.properties.avgColor.length == 3 ? `rgb(${this.image.properties.avgColor.join(',')})` : 'transparent', 'background-color': this.image.properties.avgColor && this.image.properties.avgColor.length == 3 ? `rgb(${this.image.properties.avgColor.join(',')})` : 'transparent',
'background-image': this.raw ? `url(${this.image.url})` : `url(${this.image.url}?thumbnail&size=512)` 'background-image': this.lightmode ? null : this.raw ? `url(${this.image.url})` : `url(${this.image.url}?thumbnail&size=512)`
}; };
} }
} }

View File

@ -1,20 +1,21 @@
<template> <template>
<div class="note" :class="{ renote: isRenote }"> <div class="note" :class="{ renote: isRenote, smart: $store.state.device.postStyle == 'smart' }">
<div class="reply-to" v-if="p.reply && (!os.isSignedIn || clientSettings.showReplyTarget)"> <div class="reply-to" v-if="p.reply && (!os.isSignedIn || clientSettings.showReplyTarget)">
<x-sub :note="p.reply"/> <x-sub :note="p.reply"/>
</div> </div>
<div class="renote" v-if="isRenote"> <div class="renote" v-if="isRenote">
<mk-avatar class="avatar" :user="note.user"/> <mk-avatar class="avatar" :user="note.user"/>
%fa:retweet% %fa:retweet%
<span>{{ '%i18n:!@reposted-by%'.substr(0, '%i18n:!@reposted-by%'.indexOf('{')) }}</span> <span>{{ '%i18n:@reposted-by%'.substr(0, '%i18n:@reposted-by%'.indexOf('{')) }}</span>
<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>{{ '%i18n:!@reposted-by%'.substr('%i18n:!@reposted-by%'.indexOf('}') + 1) }}</span> <span>{{ '%i18n:@reposted-by%'.substr('%i18n:@reposted-by%'.indexOf('}') + 1) }}</span>
<mk-time :time="note.createdAt"/> <mk-time :time="note.createdAt"/>
</div> </div>
<article> <article>
<mk-avatar class="avatar" :user="p.user"/> <mk-avatar class="avatar" :user="p.user" v-if="$store.state.device.postStyle != 'smart'"/>
<div class="main"> <div class="main">
<header> <header>
<mk-avatar class="avatar" :user="p.user" v-if="$store.state.device.postStyle == 'smart'"/>
<router-link class="name" :to="p.user | userPage">{{ p.user | userName }}</router-link> <router-link class="name" :to="p.user | userPage">{{ p.user | userName }}</router-link>
<span class="is-bot" v-if="p.user.host === null && p.user.isBot">bot</span> <span class="is-bot" v-if="p.user.host === null && p.user.isBot">bot</span>
<span class="username"><mk-acct :user="p.user"/></span> <span class="username"><mk-acct :user="p.user"/></span>
@ -262,6 +263,15 @@ root(isDark)
@media (min-width 500px) @media (min-width 500px)
font-size 16px font-size 16px
&.smart
> article
> .main
width 100%
> header
align-items center
margin-bottom 4px
> .renote > .renote
display flex display flex
align-items center align-items center
@ -279,11 +289,15 @@ root(isDark)
.avatar .avatar
display inline-block display inline-block
width 28px width 20px
height 28px height 20px
margin 0 8px 0 0 margin 0 8px 0 0
border-radius 6px border-radius 6px
@media (min-width 500px)
width 28px
height 28px
[data-fa] [data-fa]
margin-right 4px margin-right 4px
@ -352,13 +366,18 @@ root(isDark)
@media (min-width 500px) @media (min-width 500px)
margin-bottom 2px margin-bottom 2px
> .avatar
margin-right 8px
width 20px
height 20px
border-radius 100%
> .name > .name
display block display block
margin 0 0.5em 0 0 margin 0 0.5em 0 0
padding 0 padding 0
overflow hidden overflow hidden
color isDark ? #fff : #627079 color isDark ? #fff : #627079
font-size 1em
font-weight bold font-weight bold
text-decoration none text-decoration none
text-overflow ellipsis text-overflow ellipsis

View File

@ -12,7 +12,7 @@
<button class="more" v-if="moreNotifications" @click="fetchMoreNotifications" :disabled="fetchingMoreNotifications"> <button class="more" v-if="moreNotifications" @click="fetchMoreNotifications" :disabled="fetchingMoreNotifications">
<template v-if="fetchingMoreNotifications">%fa:spinner .pulse .fw%</template> <template v-if="fetchingMoreNotifications">%fa:spinner .pulse .fw%</template>
{{ fetchingMoreNotifications ? '%i18n:!common.loading%' : '%i18n:!@more%' }} {{ fetchingMoreNotifications ? '%i18n:common.loading%' : '%i18n:@more%' }}
</button> </button>
<p class="empty" v-if="notifications.length == 0 && !fetching">%i18n:@empty%</p> <p class="empty" v-if="notifications.length == 0 && !fetching">%i18n:@empty%</p>

View File

@ -20,7 +20,7 @@
<a @click="addVisibleUser">+ユーザーを追加</a> <a @click="addVisibleUser">+ユーザーを追加</a>
</div> </div>
<input v-show="useCw" v-model="cw" placeholder="内容への注釈 (オプション)"> <input v-show="useCw" v-model="cw" placeholder="内容への注釈 (オプション)">
<textarea v-model="text" ref="text" :disabled="posting" :placeholder="reply ? '%i18n:!@reply-placeholder%' : renote ? '%i18n:!@renote-placeholder%' : '%i18n:!@note-placeholder%'"></textarea> <textarea v-model="text" ref="text" :disabled="posting" :placeholder="reply ? '%i18n:@reply-placeholder%' : renote ? '%i18n:@renote-placeholder%' : '%i18n:@note-placeholder%'"></textarea>
<div class="attaches" v-show="files.length != 0"> <div class="attaches" v-show="files.length != 0">
<x-draggable class="files" :list="files" :options="{ animation: 150 }"> <x-draggable class="files" :list="files" :options="{ animation: 150 }">
<div class="file" v-for="file in files" :key="file.id"> <div class="file" v-for="file in files" :key="file.id">

View File

@ -94,7 +94,7 @@ export default Vue.extend({
}, },
methods: { methods: {
search() { search() {
const query = window.prompt('%i18n:!@search%'); const query = window.prompt('%i18n:@search%');
if (query == null || query == '') return; if (query == null || query == '') return;
this.$router.push('/search?q=' + encodeURIComponent(query)); this.$router.push('/search?q=' + encodeURIComponent(query));
}, },

View File

@ -3,7 +3,7 @@
<mk-notes ref="timeline" :more="existMore ? more : null"> <mk-notes ref="timeline" :more="existMore ? more : null">
<div slot="empty"> <div slot="empty">
%fa:R comments% %fa:R comments%
{{ withMedia ? '%i18n:!@no-notes-with-media%' : '%i18n:!@no-notes%' }} {{ withMedia ? '%i18n:@no-notes-with-media%' : '%i18n:@no-notes%' }}
</div> </div>
</mk-notes> </mk-notes>
</div> </div>

View File

@ -2,7 +2,7 @@
<mk-ui> <mk-ui>
<template slot="header" v-if="!fetching"> <template slot="header" v-if="!fetching">
<img :src="`${user.avatarUrl}?thumbnail&size=64`" alt=""> <img :src="`${user.avatarUrl}?thumbnail&size=64`" alt="">
{{ '%i18n:!@followers-of%'.replace('{}', name) }} {{ '%i18n:@followers-of%'.replace('{}', name) }}
</template> </template>
<mk-users-list <mk-users-list
v-if="!fetching" v-if="!fetching"
@ -49,7 +49,7 @@ export default Vue.extend({
this.user = user; this.user = user;
this.fetching = false; this.fetching = false;
document.title = '%i18n:!@followers-of%'.replace('{}', this.name) + ' | Misskey'; document.title = '%i18n:@followers-of%'.replace('{}', this.name) + ' | Misskey';
}); });
}, },
onLoaded() { onLoaded() {

View File

@ -2,7 +2,7 @@
<mk-ui> <mk-ui>
<template slot="header" v-if="!fetching"> <template slot="header" v-if="!fetching">
<img :src="`${user.avatarUrl}?thumbnail&size=64`" alt=""> <img :src="`${user.avatarUrl}?thumbnail&size=64`" alt="">
{{ '%i18n:!@following-of%'.replace('{}', name) }} {{ '%i18n:@following-of%'.replace('{}', name) }}
</template> </template>
<mk-users-list <mk-users-list
v-if="!fetching" v-if="!fetching"
@ -48,7 +48,7 @@ export default Vue.extend({
this.user = user; this.user = user;
this.fetching = false; this.fetching = false;
document.title = '%i18n:!@followers-of%'.replace('{}', this.name) + ' | Misskey'; document.title = '%i18n:@followers-of%'.replace('{}', this.name) + ' | Misskey';
}); });
}, },
onLoaded() { onLoaded() {

View File

@ -21,7 +21,7 @@ export default Vue.extend({
}, },
methods: { methods: {
fn() { fn() {
const ok = window.confirm('%i18n:!@read-all%'); const ok = window.confirm('%i18n:@read-all%');
if (!ok) return; if (!ok) return;
(this as any).api('notifications/markAsRead_all'); (this as any).api('notifications/markAsRead_all');

View File

@ -3,7 +3,7 @@
<span slot="header">%fa:search% {{ q }}</span> <span slot="header">%fa:search% {{ q }}</span>
<main v-if="!fetching"> <main v-if="!fetching">
<mk-notes :class="$style.notes" :notes="notes"> <mk-notes :class="$style.notes" :notes="notes">
<span v-if="notes.length == 0">{{ '%i18n:!@empty%'.replace('{}', q) }}</span> <span v-if="notes.length == 0">{{ '%i18n:@empty%'.replace('{}', q) }}</span>
<button v-if="existMore" @click="more" :disabled="fetching" slot="tail"> <button v-if="existMore" @click="more" :disabled="fetching" slot="tail">
<span v-if="!fetching">%i18n:@load-more%</span> <span v-if="!fetching">%i18n:@load-more%</span>
<span v-if="fetching">%i18n:common.loading%<mk-ellipsis/></span> <span v-if="fetching">%i18n:common.loading%<mk-ellipsis/></span>

View File

@ -25,7 +25,7 @@ export default Vue.extend({
} }
}, },
mounted() { mounted() {
document.title = '%i18n:!@title%'; document.title = '%i18n:@title%';
}, },
methods: { methods: {
onSelected(file) { onSelected(file) {

View File

@ -2,7 +2,7 @@
<mk-ui> <mk-ui>
<span slot="header">%fa:cog%%i18n:@settings%</span> <span slot="header">%fa:cog%%i18n:@settings%</span>
<main> <main>
<p v-html="'%i18n:!@signed-in-as%'.replace('{}', '<b>' + name + '</b>')"></p> <p v-html="'%i18n:@signed-in-as%'.replace('{}', '<b>' + name + '</b>')"></p>
<div> <div>
<x-profile/> <x-profile/>
@ -35,6 +35,13 @@
<md-switch v-model="clientSettings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</md-switch> <md-switch v-model="clientSettings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</md-switch>
</div> </div>
</div> </div>
<div>
<div class="md-body-2">%i18n:@post-style%</div>
<md-radio v-model="postStyle" value="standard">%i18n:@post-style-standard%</md-radio>
<md-radio v-model="postStyle" value="smart">%i18n:@post-style-smart%</md-radio>
</div>
</md-card-content> </md-card-content>
</md-card> </md-card>
@ -51,6 +58,10 @@
<div> <div>
<md-switch v-model="clientSettings.disableViaMobile" @change="onChangeDisableViaMobile">%i18n:@disable-via-mobile%</md-switch> <md-switch v-model="clientSettings.disableViaMobile" @change="onChangeDisableViaMobile">%i18n:@disable-via-mobile%</md-switch>
</div> </div>
<div>
<md-switch v-model="lightmode">%i18n:@i-am-under-limited-internet%</md-switch>
</div>
</md-card-content> </md-card-content>
</md-card> </md-card>
@ -67,11 +78,7 @@
</md-optgroup> </md-optgroup>
<md-optgroup label="%i18n:@specify-language%"> <md-optgroup label="%i18n:@specify-language%">
<md-option value="ja">日本語</md-option> <md-option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</md-option>
<md-option value="en">English</md-option>
<md-option value="fr">Français</md-option>
<md-option value="pl">Polski</md-option>
<md-option value="de">Deutsch</md-option>
</md-optgroup> </md-optgroup>
</md-select> </md-select>
</md-field> </md-field>
@ -87,7 +94,7 @@
<md-card-content> <md-card-content>
<p class="account" v-if="os.i.twitter"><a :href="`https://twitter.com/${os.i.twitter.screenName}`" target="_blank">@{{ os.i.twitter.screenName }}</a></p> <p class="account" v-if="os.i.twitter"><a :href="`https://twitter.com/${os.i.twitter.screenName}`" target="_blank">@{{ os.i.twitter.screenName }}</a></p>
<p> <p>
<a :href="`${apiUrl}/connect/twitter`" target="_blank">{{ os.i.twitter ? '%i18n:!@twitter-reconnect%' : '%i18n:!@twitter-connect%' }}</a> <a :href="`${apiUrl}/connect/twitter`" target="_blank">{{ os.i.twitter ? '%i18n:@twitter-reconnect%' : '%i18n:@twitter-connect%' }}</a>
<span v-if="os.i.twitter"> or </span> <span v-if="os.i.twitter"> or </span>
<a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="os.i.twitter">%i18n:@twitter-disconnect%</a> <a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="os.i.twitter">%i18n:@twitter-disconnect%</a>
</p> </p>
@ -118,7 +125,7 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import { apiUrl, version, codename } from '../../../config'; import { apiUrl, version, codename, langs } from '../../../config';
import checkForUpdate from '../../../common/scripts/check-for-update'; import checkForUpdate from '../../../common/scripts/check-for-update';
import XProfile from './settings/settings.profile.vue'; import XProfile from './settings/settings.profile.vue';
@ -133,8 +140,8 @@ export default Vue.extend({
apiUrl, apiUrl,
version, version,
codename, codename,
langs,
darkmode: localStorage.getItem('darkmode') == 'true', darkmode: localStorage.getItem('darkmode') == 'true',
lang: localStorage.getItem('lang') || '',
latestVersion: undefined, latestVersion: undefined,
checkingForUpdate: false checkingForUpdate: false
}; };
@ -143,15 +150,27 @@ export default Vue.extend({
computed: { computed: {
name(): string { name(): string {
return Vue.filter('userName')((this as any).os.i); return Vue.filter('userName')((this as any).os.i);
} },
postStyle: {
get() { return this.$store.state.device.postStyle; },
set(value) { this.$store.commit('device/set', { key: 'postStyle', value }); }
},
lightmode: {
get() { return this.$store.state.device.lightmode; },
set(value) { this.$store.commit('device/set', { key: 'lightmode', value }); }
},
lang: {
get() { return this.$store.state.device.lang; },
set(value) { this.$store.commit('device/set', { key: 'lang', value }); }
},
}, },
watch: { watch: {
darkmode() { darkmode() {
(this as any)._updateDarkmode_(this.darkmode); (this as any)._updateDarkmode_(this.darkmode);
},
lang() {
localStorage.setItem('lang', this.lang);
} }
}, },
@ -213,13 +232,13 @@ export default Vue.extend({
this.latestVersion = newer; this.latestVersion = newer;
if (newer == null) { if (newer == null) {
(this as any).apis.dialog({ (this as any).apis.dialog({
title: '%i18n:!@no-updates%', title: '%i18n:@no-updates%',
text: '%i18n:!@no-updates-desc%' text: '%i18n:@no-updates-desc%'
}); });
} else { } else {
(this as any).apis.dialog({ (this as any).apis.dialog({
title: '%i18n:!@update-available%', title: '%i18n:@update-available%',
text: '%i18n:!@update-available-desc%' text: '%i18n:@update-available-desc%'
}); });
} }
}); });

View File

@ -7,7 +7,14 @@
<md-card-content> <md-card-content>
<md-field> <md-field>
<label>%i18n:@name%</label> <label>%i18n:@name%</label>
<md-input v-model="name" :disabled="saving"/> <md-input v-model="name" :disabled="saving" md-counter="30"/>
</md-field>
<md-field>
<label>%i18n:@account%</label>
<span class="md-prefix">@</span>
<md-input v-model="username" readonly></md-input>
<span class="md-suffix">@{{ host }}</span>
</md-field> </md-field>
<md-field> <md-field>
@ -20,11 +27,12 @@
<md-icon>%fa:birthday-cake%</md-icon> <md-icon>%fa:birthday-cake%</md-icon>
<label>%i18n:@birthday%</label> <label>%i18n:@birthday%</label>
<md-input type="date" v-model="birthday" :disabled="saving"/> <md-input type="date" v-model="birthday" :disabled="saving"/>
<span class="md-helper-text">%i18n:@will-be-published%</span>
</md-field> </md-field>
<md-field> <md-field>
<label>%i18n:@description%</label> <label>%i18n:@description%</label>
<md-textarea v-model="description" :disabled="saving"/> <md-textarea v-model="description" :disabled="saving" md-counter="500"/>
</md-field> </md-field>
<md-field> <md-field>
@ -54,12 +62,14 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import { apiUrl } from '../../../../config'; import { apiUrl, host } from '../../../../config';
export default Vue.extend({ export default Vue.extend({
data() { data() {
return { return {
host,
name: null, name: null,
username: null,
location: null, location: null,
description: null, description: null,
birthday: null, birthday: null,
@ -72,6 +82,7 @@ export default Vue.extend({
created() { created() {
this.name = (this as any).os.i.name || ''; this.name = (this as any).os.i.name || '';
this.username = (this as any).os.i.username;
this.location = (this as any).os.i.profile.location; this.location = (this as any).os.i.profile.location;
this.description = (this as any).os.i.description; this.description = (this as any).os.i.description;
this.birthday = (this as any).os.i.profile.birthday; this.birthday = (this as any).os.i.profile.birthday;
@ -147,7 +158,7 @@ export default Vue.extend({
(this as any).os.i.bannerId = i.bannerId; (this as any).os.i.bannerId = i.bannerId;
(this as any).os.i.bannerUrl = i.bannerUrl; (this as any).os.i.bannerUrl = i.bannerUrl;
alert('%i18n:!@saved%'); alert('%i18n:@saved%');
}); });
} }
} }

View File

@ -65,7 +65,7 @@ export default Vue.extend({
computed: { computed: {
widgets(): any[] { widgets(): any[] {
return this.$store.state.settings.data.mobileHome; return this.$store.state.settings.mobileHome;
} }
}, },

View File

@ -1,3 +1,6 @@
input
min-width 0px
input:not([type]) input:not([type])
input[type='text'] input[type='text']
input[type='password'] input[type='password']

View File

@ -1,4 +1,6 @@
import Vuex from 'vuex'; import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate';
import MiOS from './mios'; import MiOS from './mios';
const defaultSettings = { const defaultSettings = {
@ -14,14 +16,29 @@ const defaultSettings = {
showRenotedMyNotes: true showRenotedMyNotes: true
}; };
const defaultDeviceSettings = {
apiViaStream: true,
autoPopout: false,
enableSounds: true,
soundVolume: 0.5,
lang: null,
preventUpdate: false,
debug: false,
lightmode: false,
postStyle: 'standard'
};
export default (os: MiOS) => new Vuex.Store({ export default (os: MiOS) => new Vuex.Store({
plugins: [store => { plugins: [store => {
store.subscribe((mutation, state) => { store.subscribe((mutation, state) => {
if (mutation.type.startsWith('settings/')) { if (mutation.type.startsWith('settings/')) {
localStorage.setItem('settings', JSON.stringify(state.settings.data)); localStorage.setItem('settings', JSON.stringify(state.settings));
} }
}); });
}], }, createPersistedState({
paths: ['device'],
filter: mut => mut.type.startsWith('device/')
})],
state: { state: {
indicate: false, indicate: false,
@ -39,50 +56,60 @@ export default (os: MiOS) => new Vuex.Store({
}, },
modules: { modules: {
settings: { device: {
namespaced: true, namespaced: true,
state: { state: defaultDeviceSettings,
data: defaultSettings
},
mutations: { mutations: {
set(state, x: { key: string; value: any }) { set(state, x: { key: string; value: any }) {
state.data[x.key] = x.value; state[x.key] = x.value;
}
}
},
settings: {
namespaced: true,
state: defaultSettings,
mutations: {
set(state, x: { key: string; value: any }) {
state[x.key] = x.value;
}, },
setHome(state, data) { setHome(state, data) {
state.data.home = data; state.home = data;
}, },
setHomeWidget(state, x) { setHomeWidget(state, x) {
const w = state.data.home.find(w => w.id == x.id); const w = state.home.find(w => w.id == x.id);
if (w) { if (w) {
w.data = x.data; w.data = x.data;
} }
}, },
addHomeWidget(state, widget) { addHomeWidget(state, widget) {
state.data.home.unshift(widget); state.home.unshift(widget);
}, },
setMobileHome(state, data) { setMobileHome(state, data) {
state.data.mobileHome = data; state.mobileHome = data;
}, },
setMobileHomeWidget(state, x) { setMobileHomeWidget(state, x) {
const w = state.data.mobileHome.find(w => w.id == x.id); const w = state.mobileHome.find(w => w.id == x.id);
if (w) { if (w) {
w.data = x.data; w.data = x.data;
} }
}, },
addMobileHomeWidget(state, widget) { addMobileHomeWidget(state, widget) {
state.data.mobileHome.unshift(widget); state.mobileHome.unshift(widget);
}, },
removeMobileHomeWidget(state, widget) { removeMobileHomeWidget(state, widget) {
state.data.mobileHome = state.data.mobileHome.filter(w => w.id != widget.id); state.mobileHome = state.mobileHome.filter(w => w.id != widget.id);
} }
}, },
@ -108,7 +135,7 @@ export default (os: MiOS) => new Vuex.Store({
ctx.commit('addHomeWidget', widget); ctx.commit('addHomeWidget', widget);
os.api('i/update_home', { os.api('i/update_home', {
home: ctx.state.data.home home: ctx.state.home
}); });
}, },
@ -116,7 +143,7 @@ export default (os: MiOS) => new Vuex.Store({
ctx.commit('addMobileHomeWidget', widget); ctx.commit('addMobileHomeWidget', widget);
os.api('i/update_mobile_home', { os.api('i/update_mobile_home', {
home: ctx.state.data.mobileHome home: ctx.state.mobileHome
}); });
}, },
@ -124,7 +151,7 @@ export default (os: MiOS) => new Vuex.Store({
ctx.commit('removeMobileHomeWidget', widget); ctx.commit('removeMobileHomeWidget', widget);
os.api('i/update_mobile_home', { os.api('i/update_mobile_home', {
home: ctx.state.data.mobileHome.filter(w => w.id != widget.id) home: ctx.state.mobileHome.filter(w => w.id != widget.id)
}); });
} }
} }

View File

@ -194,7 +194,12 @@ cluster.on('exit', worker => {
// Display detail of unhandled promise rejection // Display detail of unhandled promise rejection
process.on('unhandledRejection', console.dir); process.on('unhandledRejection', console.dir);
// Dying away... // Display detail of uncaught exception
process.on('exit', () => { process.on('uncaughtException', err => {
Logger.info('The process is going exit'); console.error(err);
});
// Dying away...
process.on('exit', code => {
Logger.info(`The process is going exit (${code})`);
}); });

View File

@ -60,7 +60,7 @@ const entry = {
const output = { const output = {
path: __dirname + '/built/client/assets', path: __dirname + '/built/client/assets',
filename: `[name].${version}.-.${isProduction ? 'min' : 'raw'}.js` filename: `[name].${version}.-.js`
}; };
//#region Define consts //#region Define consts
@ -78,6 +78,7 @@ const consts = {
_WS_URL_: config.ws_url, _WS_URL_: config.ws_url,
_DEV_URL_: config.dev_url, _DEV_URL_: config.dev_url,
_LANG_: '%lang%', _LANG_: '%lang%',
_LANGS_: Object.keys(locales).map(l => [l, locales[l].meta.lang]),
_HOST_: config.host, _HOST_: config.host,
_HOSTNAME_: config.hostname, _HOSTNAME_: config.hostname,
_URL_: config.url, _URL_: config.url,
@ -110,14 +111,14 @@ const plugins = [
//#region i18n //#region i18n
langs.forEach(lang => { langs.forEach(lang => {
Object.keys(entry).forEach(file => { Object.keys(entry).forEach(file => {
let src = fs.readFileSync(`${__dirname}/built/client/assets/${file}.${version}.-.${isProduction ? 'min' : 'raw'}.js`, 'utf-8'); let src = fs.readFileSync(`${__dirname}/built/client/assets/${file}.${version}.-.js`, 'utf-8');
const i18nReplacer = new I18nReplacer(lang); const i18nReplacer = new I18nReplacer(lang);
src = src.replace(i18nReplacer.pattern, i18nReplacer.replacement); src = src.replace(i18nReplacer.pattern, i18nReplacer.replacement);
src = src.replace('%lang%', lang); src = src.replace('%lang%', lang);
fs.writeFileSync(`${__dirname}/built/client/assets/${file}.${version}.${lang}.${isProduction ? 'min' : 'raw'}.js`, src, 'utf-8'); fs.writeFileSync(`${__dirname}/built/client/assets/${file}.${version}.${lang}.js`, src, 'utf-8');
}); });
}); });
//#endregion //#endregion

View File

@ -2,17 +2,12 @@
* Replace i18n texts * Replace i18n texts
*/ */
export const pattern = /%i18n:([a-z0-9_\-@\.\!]+?)%/g; export const pattern = /%i18n:([a-z0-9_\-@\.]+?)%/g;
export const replacement = (ctx, match, key) => { export const replacement = (ctx, match, key) => {
const client = '/src/client/app/'; const client = '/src/client/app/';
let name = null; let name = null;
const shouldEscape = key[0] == '!';
if (shouldEscape) {
key = key.substr(1);
}
if (key[0] == '@') { if (key[0] == '@') {
name = ctx.src.substr(ctx.src.indexOf(client) + client.length); name = ctx.src.substr(ctx.src.indexOf(client) + client.length);
key = key.substr(1); key = key.substr(1);
@ -20,5 +15,5 @@ export const replacement = (ctx, match, key) => {
const path = name ? `${name}|${key}` : key; const path = name ? `${name}|${key}` : key;
return shouldEscape ? `%i18n:!${path}%` : `%i18n:${path}%`; return `%i18n:${path}%`;
}; };