Merge pull request #5 from syuilo/master

追従
This commit is contained in:
tamaina 2018-04-15 18:12:11 +09:00 committed by GitHub
commit f982f5e850
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
151 changed files with 1822 additions and 2703 deletions

View file

@ -12,7 +12,7 @@ url:
# 待受ポート # 待受ポート
port: port:
# TLSの設定(利用しない場合は省略可能) # TLSの設定(利用しない場合は省略してください)
https: https:
# 証明書のパス... # 証明書のパス...
key: key:

View file

@ -1,8 +1,8 @@
DONORS DONATORS
====== ========
The list of people who have sent donation for Misskey. The list of people who have sent donation for Misskey.
(no particular order) (In random order, honorific titles are omitted.)
* らふぁ * らふぁ
* 俺様 * 俺様
@ -12,6 +12,11 @@ The list of people who have sent donation for Misskey.
* 音船 https://otofune.me/ * 音船 https://otofune.me/
* aqz https://misskey.xyz/aqz * aqz https://misskey.xyz/aqz
* kotodu "虚無創作中" * kotodu "虚無創作中"
* Maya Minatsuki
* Knzk https://knzk.me/@Knzk
* ねじりわさび https://knzk.me/@y
* NCLS https://knzk.me/@imncls]
* こじま @skoji@sandbox.skoji.jp
:heart: Thanks for donating, guys! :heart: Thanks for donating, guys!

View file

@ -17,24 +17,22 @@ ultimately sophisticated new type of mini-blog based SNS.
:sparkles: Features :sparkles: Features
---------------------------------------------------------------- ----------------------------------------------------------------
* Automatically updated timeline * Automatically updated timeline
* Reactions
* Private messages * Private messages
* Two-Factor Authentication support
* ServiceWorker support * ServiceWorker support
* Web API for third-party applications
* ActivityPub compatible * ActivityPub compatible
and more! You can touch with your own eyes at https://misskey.xyz/. and more! You can touch with your own eyes at https://misskey.xyz/.
:package: Setup :package: Create your instance
---------------------------------------------------------------- ----------------------------------------------------------------
If you want to run your own instance of Misskey, If you want to run your own instance of Misskey,
please see [Setup and installation guide](./docs/setup.en.md). please see [Setup and installation guide](./docs/setup.en.md).
:yen: Donation :heart: Backers & Sponsors
---------------------------------------------------------------- ----------------------------------------------------------------
If you want to donate to Misskey, please see [this](./docs/donate.ja.md). [![Backers][backers-image]][support-url]
[![Sponsors][sponsors-image]][support-url]
[List of all donors](./DONORS.md)
:mortar_board: Notable contributors :mortar_board: Notable contributors
---------------------------------------------------------------- ----------------------------------------------------------------
@ -62,6 +60,14 @@ Misskey is an open-source software licensed under [GNU AGPLv3](LICENSE).
[himawari-badge]: https://img.shields.io/badge/%E5%8F%A4%E8%B0%B7-%E5%90%91%E6%97%A5%E8%91%B5-1684c5.svg?style=flat-square [himawari-badge]: https://img.shields.io/badge/%E5%8F%A4%E8%B0%B7-%E5%90%91%E6%97%A5%E8%91%B5-1684c5.svg?style=flat-square
[sakurako-badge]: https://img.shields.io/badge/%E5%A4%A7%E5%AE%A4-%E6%AB%BB%E5%AD%90-efb02a.svg?style=flat-square [sakurako-badge]: https://img.shields.io/badge/%E5%A4%A7%E5%AE%A4-%E6%AB%BB%E5%AD%90-efb02a.svg?style=flat-square
[backer-url]: #backers
[backer-badge]: https://opencollective.com/misskey/backers/badge.svg
[backers-image]: https://opencollective.com/misskey/backers.svg
[sponsor-url]: #sponsors
[sponsor-badge]: https://opencollective.com/misskey/sponsors/badge.svg
[sponsors-image]: https://opencollective.com/misskey/sponsors.svg
[support-url]: https://opencollective.com/misskey#support
<!-- Contributors Info --> <!-- Contributors Info -->
[syuilo-link]: https://syuilo.com [syuilo-link]: https://syuilo.com
[syuilo-icon]: https://avatars2.githubusercontent.com/u/4439005?v=3&s=70 [syuilo-icon]: https://avatars2.githubusercontent.com/u/4439005?v=3&s=70

13
cli/del-usr.js Normal file
View file

@ -0,0 +1,13 @@
const deleteUser = require('../built/models/user').deleteUser;
const args = process.argv.slice(2);
const userId = args[0];
console.log(`deleting ${userId}...`);
deleteUser(userId).then(() => {
console.log('done');
}, e => {
console.error(e);
});

View file

@ -1,29 +1,30 @@
// for Node.js interpret const { default: User, deleteUser } = require('../built/models/user');
const { default: User } = require('../../../built/models/user');
const { default: zip } = require('@prezzemolo/zip') const { default: zip } = require('@prezzemolo/zip')
const migrate = async (user) => { const migrate = async (user) => {
const result = await User.update(user._id, { try {
$set: { await deleteUser(user._id);
'username': user.username.replace(/\-/g, '_'), return true;
'username_lower': user.username_lower.replace(/\-/g, '_') } catch (e) {
return false;
} }
});
return result.ok === 1;
} }
async function main() { async function main() {
const count = await User.count({}); const count = await User.count({
uri: /#/
});
const dop = Number.parseInt(process.argv[2]) || 5 const dop = 1
const idop = ((count - (count % dop)) / dop) + 1 const idop = ((count - (count % dop)) / dop) + 1
return zip( return zip(
1, 1,
async (time) => { async (time) => {
console.log(`${time} / ${idop}`) console.log(`${time} / ${idop}`)
const doc = await User.find({}, { const doc = await User.find({
uri: /#/
}, {
limit: dop, skip: time * dop limit: dop, skip: time * dop
}) })
return Promise.all(doc.map(migrate)) return Promise.all(doc.map(migrate))

View file

@ -121,12 +121,6 @@ inquirer.prompt(form).then(as => {
}, },
url: as['url'], url: as['url'],
port: parseInt(as['port'], 10), port: parseInt(as['port'], 10),
https: {
enable: as['https'],
key: as['https_key'] || null,
cert: as['https_cert'] || null,
ca: as['https_ca'] || null
},
mongodb: { mongodb: {
host: as['mongo_host'], host: as['mongo_host'],
port: parseInt(as['mongo_port'], 10), port: parseInt(as['mongo_port'], 10),
@ -151,6 +145,14 @@ inquirer.prompt(form).then(as => {
} }
}; };
if (as['https']) {
conf.https = {
key: as['https_key'] || null,
cert: as['https_cert'] || null,
ca: as['https_ca'] || null
};
}
console.log(`Thanks. Writing the configuration to ${chalk.bold(path.resolve(configPath))}`); console.log(`Thanks. Writing the configuration to ${chalk.bold(path.resolve(configPath))}`);
try { try {

27
docs/translate.ja.md Normal file
View file

@ -0,0 +1,27 @@
Misskeyの翻訳
============
新たな言語を追加するには
----------------------
/locales 内に既にある何らかの言語ファイルをコピーして、追加したい言語名にリネームして編集してください。
Misskey内の未翻訳箇所を見つけたら
-------------------------------
1. Misskeyのソースコード内から未翻訳箇所を探してください。
- 例えば`src/client/app/mobile/views/pages/home.vue`で未翻訳箇所を見つけたとします。
2. 未翻訳箇所を`%i18n:@hoge%`のような形式の文字列に置換してください。
- `hoge`は実際にはその場に適したわかりやすい(英語の)名前にしてください。
- 例えば未翻訳箇所が「タイムライン」というテキストだった場合、`%i18n:@timeline%`のようにします。
3. /locales 内にあるそれぞれの言語ファイルを開き、1.で見つけた<strong>ファイル名(パス)</strong>のキーが存在するか確認し、無ければ作成してください。
- パスの`src/client/app/`は省略してください。
- 例えば、今回の例では`src/client/app/mobile/views/pages/home.vue`の未翻訳箇所を修正したいので、キーは`mobile/views/pages/home.vue`になります。
4. そのキーの直下に2.で置換した`hoge`の部分をキーとし、翻訳後のテキストを値とするプロパティを追加します。
- 例えば、今回の例で言うと`locales/ja.yml`に`timeline: "タイムライン"`、`locales/en.yml`に`timeline: "Timeline"`を追加します。
5. 完了です!
詳しくは、[このコミット](https://github.com/syuilo/misskey/commit/10f6d5980fa7692ccb45fbc5f843458b69b7607c)などを参考にしてください。

View file

@ -1,5 +1,5 @@
common: common:
misskey: "Note everything and share it others using Misskey." misskey: "Share everything others using Misskey."
time: time:
unknown: "unknown" unknown: "unknown"
@ -33,62 +33,19 @@ common:
confused: "Confused" confused: "Confused"
pudding: "Pudding" pudding: "Pudding"
note_categories:
music: "Music"
game: "Video Game"
anime: "Anime"
it: "IT"
gadgets: "Gadgets"
photography: "Photography"
input-message-here: "Enter message here"
send: "Send"
delete: "Delete" delete: "Delete"
loading: "Loading" loading: "Loading"
ok: "OK" ok: "OK"
update-available: "New version of Misskey is now available({newer}, current is {current}). Reload page to apply update." update-available: "New version of Misskey is now available({newer}, current is {current}). Reload page to apply update."
my-token-regenerated: "Your token is just regenerated, so you will signout." my-token-regenerated: "Your token is just regenerated, so you will signout."
tags: common/views/components/connect-failed.vue:
mk-nav-links:
about: "About"
stats: "Stats"
status: "Status"
wiki: "Wiki"
donors: "Donors"
repository: "Repository"
develop: "Developers"
mk-messaging-form:
attach-from-local: "Attach file from your pc"
attach-from-drive: "Attach file from the drive"
mk-messaging:
search-user: "Find a user"
you: "You"
no-history: "No history"
mk-messaging-message:
is-read: "Read"
deleted: "This message has been deleted"
mk-messaging-room:
empty: "No conversations"
more: "More"
no-history: "There is no more history"
resize-form: "Drag to resize"
new-message: "New message"
mk-authorized-apps:
no-apps: "No apps"
mk-error:
title: "Unable to connect to the server" title: "Unable to connect to the server"
description: "There is a problem with Internet connection, or the server may be down or maintaining. Please {try again} later." description: "There is a problem with Internet connection, or the server may be down or maintaining. Please {try again} later."
thanks: "Thank you for using Misskey." thanks: "Thank you for using Misskey."
troubleshoot: "Troubleshoot" troubleshoot: "Troubleshoot"
troubleshooter: common/views/components/connect-failed.troubleshooter.vue:
title: "TroubleShooting" title: "TroubleShooting"
network: "Network connection" network: "Network connection"
checking-network: "Checking network connection" checking-network: "Checking network connection"
@ -106,17 +63,41 @@ common:
success: "Successfully connect to the Misskey's server" success: "Successfully connect to the Misskey's server"
success-desc: "It seems to be able to connect normally. Please reload the page." success-desc: "It seems to be able to connect normally. Please reload the page."
mk-forkit: common/views/components/messaging.vue:
open-github-link: "View source on Github" search-user: "Find a user"
you: "You"
no-history: "No history"
mk-poll-editor: common/views/components/messaging-room.vue:
no-only-one-choice: "You need to enter two or more choice." empty: "No conversations"
choice-n: "Choice {}" more: "More"
remove: "Remove this choice" no-history: "There is no more history"
add: "+ Add a choice" resize-form: "Drag to resize"
destroy: "Destroy this poll" new-message: "New message"
mk-poll: common/views/components/messaging-room.form.vue:
input-message-here: "Enter message here"
send: "Send"
attach-from-local: "Attach file from your pc"
attach-from-drive: "Attach file from the drive"
common/views/components/messaging-room.message.vue:
is-read: "Read"
deleted: "This message has been deleted"
common/views/components/nav.vue:
about: "About"
stats: "Stats"
status: "Status"
wiki: "Wiki"
donors: "Donors"
repository: "Repository"
develop: "Developers"
common/views/components/note-menu.vue:
pin: "Pin to profile page"
common/views/components/poll.vue:
vote-to: "Vote to 「{}」" vote-to: "Vote to 「{}」"
vote-count: "{} votes" vote-count: "{} votes"
total-users: "{} users voted" total-users: "{} users voted"
@ -124,31 +105,31 @@ common:
show-result: "Show result" show-result: "Show result"
voted: "Voted" voted: "Voted"
mk-note-menu: common/views/components/poll-editor.vue:
pin: "Pin" no-only-one-choice: "You need to enter two or more choice."
pinned: "Pinned" choice-n: "Choice {}"
select: "Select category" remove: "Remove this choice"
categorize: "Accept" add: "+ Add a choice"
categorized: "Category reported. Thank you!" destroy: "Destroy this poll"
mk-reaction-picker: common/views/components/reaction-picker.vue:
choose-reaction: "Pick your reaction" choose-reaction: "Pick your reaction"
mk-signin: common/views/components/signin.vue:
username: "Username" username: "Username"
password: "Password" password: "Password"
token: "Token" token: "Token"
signing-in: "Signing in..." signing-in: "Signing in..."
signin: "Sign in" signin: "Sign in"
mk-signup: common/views/components/signup.vue:
username: "Username" username: "Username"
checking: "Checking..." checking: "Checking..."
available: "Available" available: "Available"
unavailable: "Unavailable" unavailable: "Unavailable"
error: "Network error" error: "Network error"
invalid-format: "Only use letters, numbers and -." invalid-format: "Only use letters, numbers and -."
too-short: "Please enter at least 3 letters" too-short: "Please enter at least 1 letters"
too-long: "Please enter within 20 letters." too-long: "Please enter within 20 letters."
password: "Password" password: "Password"
password-placeholder: "We recommend more than 8 letters." password-placeholder: "We recommend more than 8 letters."
@ -163,16 +144,16 @@ common:
create: "Create an Account" create: "Create an Account"
some-error: "Account creation failed for some reason. Please try again." some-error: "Account creation failed for some reason. Please try again."
mk-special-message: common/views/components/special-message.vue:
new-year: "Happy New Year!" new-year: "Happy New Year!"
christmas: "Merry Christmas!" christmas: "Merry Christmas!"
mk-stream-indicator: common/views/components/stream-indicator.vue:
connecting: "Connecting" connecting: "Connecting"
reconnecting: "Reconnecting" reconnecting: "Reconnecting"
connected: "Connected" connected: "Connected"
mk-twitter-setting: common/views/components/twitter-setting.vue:
description: "お使いのTwitterアカウントをお使いのMisskeyアカウントに接続しておくと、プロフィールでTwitterアカウント情報が表示されるようになったり、Twitterを用いた便利なサインインを利用できるようになります。" description: "お使いのTwitterアカウントをお使いのMisskeyアカウントに接続しておくと、プロフィールでTwitterアカウント情報が表示されるようになったり、Twitterを用いた便利なサインインを利用できるようになります。"
connected-to: "You to connected this Twitter account" connected-to: "You to connected this Twitter account"
detail: "Detail..." detail: "Detail..."
@ -180,59 +161,73 @@ common:
connect: "Connect to Twitter" connect: "Connect to Twitter"
disconnect: "Disconnect" disconnect: "Disconnect"
mk-uploader: common/views/components/uploader.vue:
waiting: "Waiting" waiting: "Waiting"
docs: common/views/widgets/broadcast.vue:
edit-this-page-on-github: "Caught a mistake or want to contribute to the documentation? " fetching: "Fetching"
edit-this-page-on-github-link: "Edit this page on Github!" no-broadcasts: "No broadcasts"
have-a-nice-day: "Have a nice day!"
next: "Next"
api: common/views/widgets/donation.vue:
entities: title: "Donation"
properties: "Properties" text: "To manage Misskey we spend money for our domain server etc.. There's no incomes for us so we need your tip. If you're interested contact {}. Thank you for your contribution!"
endpoints:
params: "Parameters"
res: "Response"
props:
name: "Name"
type: "Type"
optional: "Optional"
description: "Description"
yes: "Yes"
no: "No"
ch: common/views/widgets/photo-stream.vue:
tags: title: "Photostream"
mk-index: no-photos: "No photos"
new: "Create new channel"
channel-title: "Channel title"
mk-channel-form: common/views/widgets/server.vue:
textarea: "Write here" title: "Server info"
upload: "Upload" toggle: "Toggle views"
drive: "Drive"
note: "Do"
posting: "Doing"
desktop: desktop/views/components/activity.vue:
tags: title: "Activity"
mk-api-info: toggle: "Toggle views"
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
regenerate-token: "Regenerate the token"
enter-password: "Please enter the password"
mk-drive-browser-base-contextmenu: desktop/views/components/calendar.vue:
create-folder: "Create a folder" title: "{1} / {2}"
upload: "Upload a file" prev: "Previous month"
url-upload: "Upload from a URL" next: "Next month"
go: "Click to travel"
mk-drive-browser-window: desktop/views/components/drive-window.vue:
used: "used" used: "used"
drive: "Drive" drive: "Drive"
mk-drive-browser: desktop/views/components/drive.file.vue:
avatar: "Avatar"
banner: "Banner"
contextmenu:
rename: "Rename"
copy-url: "Copy URL"
download: "Download"
else-files: "その他..."
set-as-avatar: "Set as avatar"
set-as-banner: "Set as banner"
open-in-app: "Open in app"
add-app: "Add app"
rename-file: "Rename file"
input-new-file-name: "Enter new name"
copied: "Copied"
copied-url-to-clipboard: "Copied URL to clipboard"
desktop/views/components/drive.folder.vue:
unable-to-process: "操作を完了できません"
circular-reference-detected: "移動先のフォルダーは、移動するフォルダーのサブフォルダーです。"
unhandled-error: "Unknown error"
contextmenu:
move-to-this-folder: "Move to this folder"
show-in-new-window: "Open in new window"
rename: "Rename"
rename-folder: "Rename folder"
input-new-folder-name: "Enter new name"
desktop/views/components/drive.nav-folder.vue:
drive: "Drive"
desktop/views/components/drive.vue:
search: "Search" search: "Search"
load-more: "Load more" load-more: "Load more"
empty-draghover: "Drop Welcome!" empty-draghover: "Drop Welcome!"
@ -248,108 +243,26 @@ desktop:
may-take-time: "アップロードが完了するまで時間がかかる場合があります。" may-take-time: "アップロードが完了するまで時間がかかる場合があります。"
create-folder: "Create a folder" create-folder: "Create a folder"
folder-name: "Folder name" folder-name: "Folder name"
contextmenu:
create-folder: "Create a folder"
upload: "Upload a file"
url-upload: "Upload from a URL"
mk-drive-browser-file-contextmenu: desktop/views/components/messaging-window.vue:
rename: "Rename" title: "Messaging"
copy-url: "Copy URL"
download: "Download"
else-files: "その他..."
set-as-avatar: "Set as avatar"
set-as-banner: "Set as banner"
open-in-app: "Open in app"
add-app: "Add app"
rename-file: "Rename file"
input-new-file-name: "Enter new name"
copied: "Copied"
copied-url-to-clipboard: "Copied URL to clipboard"
mk-drive-browser-file: desktop/views/components/notes.note.vue:
avatar: "Avatar" reposted-by: "Reposted by {}"
banner: "Banner" reply: "Reply"
renote: "Renote"
add-reaction: "Add your reaction"
detail: "Show detail"
mk-drive-browser-folder-contextmenu: desktop/views/components/notifications.vue:
move-to-this-folder: "Move to this folder" more: "More"
show-in-new-window: "Open in new window" empty: "No notifications"
rename: "Rename"
rename-folder: "Rename folder"
input-new-folder-name: "Enter new name"
mk-drive-browser-folder: desktop/views/components/post-form.vue:
unable-to-process: "操作を完了できません"
circular-reference-detected: "移動先のフォルダーは、移動するフォルダーのサブフォルダーです。"
unhandled-error: "Unknown error"
mk-drive-browser-nav-folder:
drive: "Drive"
mk-selectdrive-page:
title: "Choose a file(s)"
ok: "OK"
cancel: "Cancel"
upload: "Upload a file(s) from you PC"
mk-ui-header-nav:
home: "Home"
messaging: "Messages"
ch: "Channels"
info: "News"
mk-ui-header-search:
placeholder: "Search"
mk-ui-header-account:
profile: "Your profile"
drive: "Drive"
mentions: "Mentions"
settings: "Settings"
signout: "Sign out"
mk-ui-header-note-button:
note: "Compose new Post"
mk-ui-header-notifications:
title: "Notifications"
mk-profile-setting:
avatar: "Avatar"
choice-avatar: "Choice an image"
name: "Name"
location: "Location"
description: "Description"
birthday: "Birthday"
save: "Update profile"
mk-password-setting:
reset: "Change your password"
enter-current-password: "Enter the current password"
enter-new-password: "Enter the new password"
enter-new-password-again: "Enter the new password again"
not-match: "New password not matched"
changed: "Password updated successfully"
mk-2fa-setting:
intro: "If you set up 2-step verification, you will need not only a password at sign-in but also a pre-registered physical device (such as your smartphone), which will improve security. "
detail: "See details..."
url: "https://www.google.com/landing/2step/"
caution: "As a caveat, security improves, but you can not sign in to Misskey if you lose a registered device, etc."
register: "Register a device"
already-registered: "The setting has already been completed."
unregister: "Disable"
unregistered: "Two-step authentication has been disabled."
enter-password: "Enter the password"
authenticator: "First, you need install Google Authenticator to your device:"
howtoinstall: "How to install"
scan: "Next, please scan displayed QR code:"
done: "Please enter the token displaying in your device:"
submit: "Submit"
success: "Setup completed successfully!"
failed: "Failed to setup. please ensure that the token is correct."
info: "From the next sign in, enter the token that is displayed on the device in addition to the password."
mk-mute-setting:
no-users: "No muted users"
mk-post-form:
note-placeholder: "What's happening?" note-placeholder: "What's happening?"
reply-placeholder: "Reply to this note..." reply-placeholder: "Reply to this note..."
quote-placeholder: "Quote this note..." quote-placeholder: "Quote this note..."
@ -370,18 +283,27 @@ desktop:
create-poll: "Create a poll" create-poll: "Create a poll"
text-remain: "{} chars remaining" text-remain: "{} chars remaining"
mk-post-form-window: desktop/views/components/post-form-window.vue:
note: "New note" note: "New note"
reply: "Reply" reply: "Reply"
attaches: "{} media attached" attaches: "{} media attached"
uploading-media: "Uploading {} media" uploading-media: "Uploading {} media"
mk-note-page: desktop/views/components/renote-form.vue:
prev: "Previous note" quote: "Quote..."
next: "Next note" cancel: "Cancel"
renote: "Renote"
reposting: "Reposting..."
success: "Reposted!"
failure: "Failed to Renote"
mk-settings: desktop/views/components/renote-form-window.vue:
title: "Are you sure you want to renote this note?"
desktop/views/components/settings.vue:
profile: "Profile" profile: "Profile"
notification: "Notification"
apps: "Apps"
mute: "Mute" mute: "Mute"
drive: "Drive" drive: "Drive"
security: "Security" security: "Security"
@ -390,181 +312,242 @@ desktop:
other: "Other" other: "Other"
license: "License" license: "License"
mk-timeline-note: desktop/views/components/settings.2fa.vue:
reposted-by: "Reposted by {}" intro: "If you set up 2-step verification, you will need not only a password at sign-in but also a pre-registered physical device (such as your smartphone), which will improve security. "
reply: "Reply" detail: "See details..."
renote: "Renote" url: "https://www.google.com/landing/2step/"
add-reaction: "Add your reaction" caution: "As a caveat, security improves, but you can not sign in to Misskey if you lose a registered device, etc."
detail: "Show detail" register: "Register a device"
already-registered: "The setting has already been completed."
unregister: "Disable"
unregistered: "Two-step authentication has been disabled."
enter-password: "Enter the password"
authenticator: "First, you need install Google Authenticator to your device:"
howtoinstall: "How to install"
scan: "Next, please scan displayed QR code:"
done: "Please enter the token displaying in your device:"
submit: "Submit"
success: "Setup completed successfully!"
failed: "Failed to setup. please ensure that the token is correct."
info: "From the next sign in, enter the token that is displayed on the device in addition to the password."
mk-notifications: desktop/views/components/settings.api.vue:
more: "More" intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
regenerate-token: "Regenerate the token"
enter-password: "Please enter the password"
mk-notifications-home-widget: desktop/views/components/settings.app.vue:
no-apps: "No authorized apps"
desktop/views/components/settings.mute.vue:
no-users: "No muted users"
desktop/views/components/settings.password.vue:
reset: "Change your password"
enter-current-password: "Enter the current password"
enter-new-password: "Enter the new password"
enter-new-password-again: "Enter the new password again"
not-match: "New password not matched"
changed: "Password updated successfully"
desktop/views/components/settings.profile.vue:
avatar: "Avatar"
choice-avatar: "Choice an image"
name: "Name"
location: "Location"
description: "Description"
birthday: "Birthday"
save: "Update profile"
desktop/views/components/ui.header.account.vue:
profile: "Your profile"
drive: "Drive"
mentions: "Mentions"
customize: "Customize"
settings: "Settings"
signout: "Sign out"
desktop/views/components/ui.header.nav.vue:
home: "Home"
messaging: "Messages"
game: "Game"
desktop/views/components/ui.header.notifications.vue:
title: "Notifications" title: "Notifications"
settings: "Notification settings"
mk-server-home-widget: desktop/views/components/ui.header.post.vue:
title: "Server info" post: "Compose new Post"
toggle: "Toggle views"
mk-activity-widget: desktop/views/components/ui.header.search.vue:
title: "Activity" placeholder: "Search"
toggle: "Toggle views"
mk-user-recommendation-home-widget: desktop/views/pages/note.vue:
title: "Recommended users" prev: "Previous note"
refresh: "Show others" next: "Next note"
no-one: "No one"
mk-recommended-polls-home-widget: desktop/views/pages/selectdrive.vue:
title: "Polls" title: "Choose a file(s)"
refresh: "Show others" ok: "OK"
nothing: "Nothing"
mk-trends-home-widget:
title: "Trend"
refresh: "Show others"
nothing: "Nothing"
mk-photo-stream-home-widget:
title: "Photostream"
no-photos: "No photos"
mk-donation-home-widget:
title: "Donation"
text: "To manage Misskey we spend money for our domain server etc.. There's no incomes for us so we need your tip. If you're interested contact {}. Thank you for your contribution!"
mk-channel-home-widget:
title: "Channel"
settings: "Widget settings"
get-started: "Please click the cog in the upper right to specify the channel to receive"
mk-calendar-widget:
title: "{1} / {2}"
prev: "Previous month"
next: "Next month"
go: "Click to travel"
mk-post-form-home-widget:
title: "Post"
note: "Post"
placeholder: "What's happening?"
mk-access-log-home-widget:
title: "Access log"
mk-messaging-home-widget:
title: "Messaging"
mk-broadcast-home-widget:
fetching: "Fetching"
no-broadcasts: "No broadcasts"
have-a-nice-day: "Have a nice day!"
next: "Next"
mk-renote-form:
quote: "Quote..."
cancel: "Cancel" cancel: "Cancel"
renote: "Renote" upload: "Upload a file(s) from you PC"
reposting: "Reposting..."
success: "Reposted!"
failure: "Failed to Renote"
mk-renote-form-window: desktop/views/pages/user/user.followers-you-know.vue:
title: "Are you sure you want to renote this note?" title: "Followers you know"
loading: "Loading"
no-users: "No users"
mk-user: desktop/views/pages/user/user.friends.vue:
title: "Frequently replied"
loading: "Loading"
no-users: "No users"
desktop/views/pages/user/user.home.vue:
last-used-at: "Last used at" last-used-at: "Last used at"
desktop/views/pages/user/user.photos.vue:
title: "Photos"
loading: "Loading"
no-photos: "No photos"
desktop/views/pages/user/user.profile.vue:
follows-you: "Follows you" follows-you: "Follows you"
mute: "Mute" mute: "Mute"
muted: "Muting" muted: "Muting"
unmute: "Unmute" unmute: "Unmute"
photos: desktop/views/widgets/messaging.vue:
title: "Photos" title: "Messaging"
loading: "Loading"
no-photos: "No photos"
frequently-replied-users: desktop/views/widgets/notifications.vue:
title: "Frequently replied" title: "Notifications"
loading: "Loading" settings: "Settings"
no-users: "No users"
followers-you-know: desktop/views/widgets/polls.vue:
title: "Followers you know" title: "Polls"
loading: "Loading" refresh: "Show others"
no-users: "No users" nothing: "Nothing"
mobile: desktop/views/widgets/post-form.vue:
tags: title: "Post"
mk-selectdrive-page: note: "Post"
select-file: "Select file(s)" placeholder: "What's happening?"
mk-drive-file-viewer: desktop/views/widgets/trends.vue:
title: "Trend"
refresh: "Show others"
nothing: "Nothing"
desktop/views/widgets/users.vue:
title: "Recommended users"
refresh: "Show others"
no-one: "No one"
desktop/views/widgets/channel.vue:
title: "Channel"
settings: "Widget settings"
get-started: "Please click the cog in the upper right to specify the channel to receive"
mobile/views/components/drive.vue:
drive: "Drive"
used: "used"
folder-count: "Folder(s)"
count-separator: ", "
file-count: "File(s)"
load-more: "Load more"
nothing-in-drive: "Nothing"
folder-is-empty: "This folder is empty"
mobile/views/components/drive-file-chooser.vue:
select-file: "Choose a file"
mobile/views/components/drive-folder-chooser.vue:
select-folder: "Choose a folder"
mobile/views/components/drive.file-detail.vue:
download: "Download" download: "Download"
rename: "Rename" rename: "Rename"
move: "Move" move: "Move"
hash: "Hash (md5)" hash: "Hash (md5)"
exif: "EXIF" exif: "EXIF"
mk-entrance-signin: mobile/views/components/follow-button.vue:
signup: "Sign up" follow: "Follow"
unfollow: "Unfollow"
mobile/views/components/note.vue:
reposted-by: "Renoted by {}"
mobile/views/components/note-detail.vue:
reply: "Reply"
reaction: "Reaction"
mobile/views/components/notifications.vue:
more: "More"
empty: "No notifications"
mobile/views/components/post-form.vue:
submit: "Post"
reply-placeholder: "Reply to this note..."
note-placeholder: "What's happening?"
mobile/views/components/sub-note-content.vue:
media-count: "{} media"
poll: "Poll"
mobile/views/components/timeline.vue:
empty: "No notes"
load-more: "More"
mobile/views/components/ui.nav.vue:
home: "Home"
notifications: "Notifications"
messaging: "Messages"
drive: "Drive"
settings: "Settings"
about: "About Misskey" about: "About Misskey"
search: "Search"
mk-entrance-signup: mobile/views/components/user-timeline.vue:
cancel: "Cancel" no-notes: "This user seems never note"
no-notes-with-media: "There is no notes with media"
load-more: "More"
mk-authorized-apps-page: mobile/views/components/users-list.vue:
application: "Applications" all: "All"
known: "You know"
load-more: "More"
mk-signin-history-page: mobile/views/pages/drive.vue:
signin-history: "Sign in history"
mk-twitter-setting-page:
twitter-integration: "Twitter integration"
mk-drive-page:
drive: "Drive" drive: "Drive"
mk-home: mobile/views/pages/followers.vue:
home: "Home" followers-of: "Followers of {}"
mk-messaging-room-page: mobile/views/pages/following.vue:
message: "Messaging" following-of: "Following of {}"
mk-messaging-page: mobile/views/pages/home.vue:
message: "Messaging" timeline: "Timeline"
mk-notifications-page: mobile/views/pages/messaging.vue:
notifications: "Notifications" messaging: "Messaging"
read-all: "Are you sure you want to mark all unread notifications as read?"
mk-note-page: mobile/views/pages/messaging-room.vue:
messaging: "Messaging"
mobile/views/pages/note.vue:
title: "Post" title: "Post"
prev: "Previous note" prev: "Previous note"
next: "Next note" next: "Next note"
mk-search-page: mobile/views/pages/notifications.vue:
search: "Search" notifications: "Notifications"
read-all: "Are you sure you want to mark all unread notifications as read?"
mk-settings: mobile/views/pages/profile-setting.vue:
signed-in-as: "Signed in as {}" title: "Profile settings"
mk-settings-page:
profile: "Profile"
applications: "Applications"
twitter-integration: "Twitter integration"
signin-history: "Sign in history"
link: "MisskeyLink"
settings: "Settings"
signout: "Sign out"
mk-profile-setting-page:
title: "Profile Settings"
mk-profile-setting:
will-be-published: "These profiles will be published." will-be-published: "These profiles will be published."
name: "Name" name: "Name"
location: "Location" location: "Location"
@ -579,84 +562,22 @@ mobile:
save: "Save" save: "Save"
saved: "Profile updated successfully" saved: "Profile updated successfully"
mk-user-followers-page: mobile/views/pages/search.vue:
followers-of: "Followers of {}" search: "Search"
empty: "「{}」に関する投稿は見つかりませんでした。"
mk-user-following-page: mobile/views/pages/selectdrive.vue:
following-of: "Following of {}"
mk-drive-folder-selector:
select-folder: "Choose a folder"
mk-drive-selector:
select-file: "Choose a file" select-file: "Choose a file"
mk-drive: mobile/views/pages/settings.vue:
drive: "Drive" signed-in-as: "Signed in as {}"
used: "used" profile: "Profile"
folder-count: "Folder(s)" twitter-integration: "Twitter integration"
count-separator: ", " signin-history: "Sign in history"
file-count: "File(s)"
load-more: "Load more"
nothing-in-drive: "Nothing"
folder-is-empty: "This folder is empty"
mk-follow-button:
follow: "Follow"
unfollow: "Unfollow"
mk-home-timeline:
empty-timeline: "There is no notes"
mk-notifications:
more: "More"
empty: "No notifications"
mk-note-detail:
reply: "Reply"
reaction: "Reaction"
mk-post-form:
submit: "Post"
reply-placeholder: "Reply to this note..."
note-placeholder: "What's happening?"
mk-search-notes:
empty: "There is no note related to the 「{}」"
mk-sub-note-content:
media-count: "{} media"
poll: "Poll"
mk-timeline-note:
reposted-by: "Reposted by {}"
mk-timeline:
empty: "No notes"
load-more: "More"
mk-ui-nav:
home: "Home"
notifications: "Notifications"
messaging: "Messages"
ch: "Channels"
drive: "Drive"
settings: "Settings" settings: "Settings"
about: "About Misskey" signout: "Sign out"
search: "Search"
mk-user-followers: mobile/views/pages/user.vue:
no-users: "No followers."
mk-user-following:
no-users: "No following."
mk-user-timeline:
no-notes: "This user seems never note"
no-notes-with-media: "There is no notes with media"
load-more: "More"
mk-user:
follows-you: "Follows you" follows-you: "Follows you"
following: "Following" following: "Following"
followers: "Followers" followers: "Followers"
@ -665,7 +586,7 @@ mobile:
timeline: "Timeline" timeline: "Timeline"
media: "Media" media: "Media"
mk-user-overview: mobile/views/pages/user/home.vue:
recent-notes: "Recent notes" recent-notes: "Recent notes"
images: "Images" images: "Images"
activity: "Activity" activity: "Activity"
@ -675,37 +596,36 @@ mobile:
followers-you-know: "Followers you know" followers-you-know: "Followers you know"
last-used-at: "Last used at" last-used-at: "Last used at"
mk-user-overview-notes: mobile/views/pages/user/home.followers-you-know.vue:
loading: "Loading"
no-users: "No users"
mobile/views/pages/user/home.friends.vue:
loading: "Loading"
no-users: "No users"
mobile/views/pages/user/home.notes.vue:
loading: "Loading" loading: "Loading"
no-notes: "No notes" no-notes: "No notes"
mk-user-overview-photos: mobile/views/pages/user/home.photos.vue:
loading: "Loading" loading: "Loading"
no-photos: "No photos" no-photos: "No photos"
mk-user-overview-keywords: docs:
no-keywords: "No keywords" edit-this-page-on-github: "Caught a mistake or want to contribute to the documentation? "
edit-this-page-on-github-link: "Edit this page on Github!"
mk-user-overview-domains: api:
no-domains: "No domains" entities:
properties: "Properties"
mk-user-overview-frequently-replied-users: endpoints:
loading: "Loading" params: "Parameters"
no-users: "No users" res: "Response"
props:
mk-user-overview-followers-you-know: name: "Name"
loading: "Loading" type: "Type"
no-users: "No users" optional: "Optional"
description: "Description"
mk-users-list: yes: "Yes"
all: "All" no: "No"
known: "You know"
load-more: "More"
stats:
notes-count: "Number of all notes"
users-count: "Number of all users"
status:
all-systems-maybe-operational: "All systems maybe operational"
what-is-this-site: ""

View file

@ -11,7 +11,7 @@ const loadLang = lang => yaml.safeLoad(
const native = loadLang('ja'); const native = loadLang('ja');
const langs = { const langs = {
//'en': loadLang('en'), 'en': loadLang('en'),
'ja': native 'ja': native
}; };

View file

@ -1,5 +1,5 @@
common: common:
misskey: "Misskeyに何でも投稿して皆と共有しましょう。" misskey: "Misskeyで皆と共有しよう。"
time: time:
unknown: "なぞのじかん" unknown: "なぞのじかん"
@ -33,62 +33,19 @@ common:
confused: "こまこまのこまり" confused: "こまこまのこまり"
pudding: "Pudding" pudding: "Pudding"
note_categories:
music: "音楽"
game: "ゲーム"
anime: "アニメ"
it: "IT"
gadgets: "ガジェット"
photography: "写真"
input-message-here: "ここにメッセージを入力"
send: "送信"
delete: "削除" delete: "削除"
loading: "読み込み中" loading: "読み込み中"
ok: "わかった" ok: "わかった"
update-available: "Misskeyの新しいバージョンがあります({newer}。現在{current}を利用中)。ページを再度読み込みすると更新が適用されます。" update-available: "Misskeyの新しいバージョンがあります({newer}。現在{current}を利用中)。ページを再度読み込みすると更新が適用されます。"
my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。"
tags: common/views/components/connect-failed.vue:
mk-nav-links:
about: "Misskeyについて"
stats: "統計"
status: "ステータス"
wiki: "Wiki"
donors: "ドナー"
repository: "リポジトリ"
develop: "開発者"
mk-messaging-form:
attach-from-local: "PCからファイルを添付する"
attach-from-drive: "ドライブからファイルを添付する"
mk-messaging:
search-user: "ユーザーを探す"
you: "あなた"
no-history: "履歴はありません"
mk-messaging-message:
is-read: "既読"
deleted: "このメッセージは削除されました"
mk-messaging-room:
empty: "このユーザーと話したことはありません"
more: "もっと読む"
no-history: "これより過去の履歴はありません"
resize-form: "ドラッグしてフォームの広さを調整"
new-message: "新しいメッセージがあります"
mk-authorized-apps:
no-apps: "連携しているアプリケーションはありません"
mk-error:
title: "サーバーに接続できません" title: "サーバーに接続できません"
description: "インターネット回線に問題があるか、サーバーがダウンまたはメンテナンスしている可能性があります。しばらくしてから{再度お試し}ください。" description: "インターネット回線に問題があるか、サーバーがダウンまたはメンテナンスしている可能性があります。しばらくしてから{再度お試し}ください。"
thanks: "いつもMisskeyをご利用いただきありがとうございます。" thanks: "いつもMisskeyをご利用いただきありがとうございます。"
troubleshoot: "トラブルシュート" troubleshoot: "トラブルシュート"
troubleshooter: common/views/components/connect-failed.troubleshooter.vue:
title: "トラブルシューティング" title: "トラブルシューティング"
network: "ネットワーク接続" network: "ネットワーク接続"
checking-network: "ネットワーク接続を確認中" checking-network: "ネットワーク接続を確認中"
@ -106,17 +63,41 @@ common:
success: "Misskeyのサーバーに接続できました" success: "Misskeyのサーバーに接続できました"
success-desc: "正常に接続できるようです。ページを再度読み込みしてください。" success-desc: "正常に接続できるようです。ページを再度読み込みしてください。"
mk-forkit: common/views/components/messaging.vue:
open-github-link: "View source on Github" search-user: "ユーザーを探す"
you: "あなた"
no-history: "履歴はありません"
mk-poll-editor: common/views/components/messaging-room.vue:
no-only-one-choice: "投票には、選択肢が最低2つ必要です" empty: "このユーザーと話したことはありません"
choice-n: "選択肢{}" more: "もっと読む"
remove: "この選択肢を削除" no-history: "これより過去の履歴はありません"
add: "+選択肢を追加" resize-form: "ドラッグしてフォームの広さを調整"
destroy: "投票を破棄" new-message: "新しいメッセージがあります"
mk-poll: common/views/components/messaging-room.form.vue:
input-message-here: "ここにメッセージを入力"
send: "送信"
attach-from-local: "PCからファイルを添付する"
attach-from-drive: "ドライブからファイルを添付する"
common/views/components/messaging-room.message.vue:
is-read: "既読"
deleted: "このメッセージは削除されました"
common/views/components/nav.vue:
about: "Misskeyについて"
stats: "統計"
status: "ステータス"
wiki: "Wiki"
donors: "ドナー"
repository: "リポジトリ"
develop: "開発者"
common/views/components/note-menu.vue:
pin: "ピン留め"
common/views/components/poll.vue:
vote-to: "「{}」に投票する" vote-to: "「{}」に投票する"
vote-count: "{}票" vote-count: "{}票"
total-users: "{}人が投票" total-users: "{}人が投票"
@ -124,24 +105,24 @@ common:
show-result: "結果を見る" show-result: "結果を見る"
voted: "投票済み" voted: "投票済み"
mk-note-menu: common/views/components/poll-editor.vue:
pin: "ピン留め" no-only-one-choice: "投票には、選択肢が最低2つ必要です"
pinned: "ピン留めしました" choice-n: "選択肢{}"
select: "カテゴリを選択" remove: "この選択肢を削除"
categorize: "決定" add: "+選択肢を追加"
categorized: "カテゴリを報告しました。これによりMisskeyが賢くなり、投稿の自動カテゴライズに役立てられます。ご協力ありがとうございました。" destroy: "投票を破棄"
mk-reaction-picker: common/views/components/reaction-picker.vue:
choose-reaction: "リアクションを選択" choose-reaction: "リアクションを選択"
mk-signin: common/views/components/signin.vue:
username: "ユーザー名" username: "ユーザー名"
password: "パスワード" password: "パスワード"
token: "トークン" token: "トークン"
signing-in: "やってます..." signing-in: "やってます..."
signin: "サインイン" signin: "サインイン"
mk-signup: common/views/components/signup.vue:
username: "ユーザー名" username: "ユーザー名"
checking: "確認しています..." checking: "確認しています..."
available: "利用できます" available: "利用できます"
@ -163,16 +144,16 @@ common:
create: "アカウント作成" create: "アカウント作成"
some-error: "何らかの原因によりアカウントの作成に失敗しました。再度お試しください。" some-error: "何らかの原因によりアカウントの作成に失敗しました。再度お試しください。"
mk-special-message: common/views/components/special-message.vue:
new-year: "Happy New Year!" new-year: "Happy New Year!"
christmas: "Merry Christmas!" christmas: "Merry Christmas!"
mk-stream-indicator: common/views/components/stream-indicator.vue:
connecting: "接続中" connecting: "接続中"
reconnecting: "再接続中" reconnecting: "再接続中"
connected: "接続完了" connected: "接続完了"
mk-twitter-setting: common/views/components/twitter-setting.vue:
description: "お使いのTwitterアカウントをお使いのMisskeyアカウントに接続しておくと、プロフィールでTwitterアカウント情報が表示されるようになったり、Twitterを用いた便利なサインインを利用できるようになります。" description: "お使いのTwitterアカウントをお使いのMisskeyアカウントに接続しておくと、プロフィールでTwitterアカウント情報が表示されるようになったり、Twitterを用いた便利なサインインを利用できるようになります。"
connected-to: "次のTwitterアカウントに接続されています" connected-to: "次のTwitterアカウントに接続されています"
detail: "詳細..." detail: "詳細..."
@ -180,59 +161,73 @@ common:
connect: "Twitterと接続する" connect: "Twitterと接続する"
disconnect: "切断する" disconnect: "切断する"
mk-uploader: common/views/components/uploader.vue:
waiting: "待機中" waiting: "待機中"
docs: common/views/widgets/broadcast.vue:
edit-this-page-on-github: "間違いや改善点を見つけましたか?" fetching: "確認中"
edit-this-page-on-github-link: "このページをGitHubで編集" no-broadcasts: "お知らせはありません"
have-a-nice-day: "良い一日を!"
next: "次"
api: common/views/widgets/donation.vue:
entities: title: "寄付のお願い"
properties: "プロパティ" text: "Misskeyの運営にはドメイン、サーバー等のコストが掛かります。Misskeyは広告を掲載したりしないため、収入を皆様からの寄付に頼っています。もしご興味があれば、{}までご連絡ください。ご協力ありがとうございます。"
endpoints:
params: "パラメータ"
res: "レスポンス"
props:
name: "名前"
type: "型"
optional: "オプション"
description: "説明"
yes: "はい"
no: "いいえ"
ch: common/views/widgets/photo-stream.vue:
tags: title: "フォトストリーム"
mk-index: no-photos: "写真はありません"
new: "チャンネルを作成"
channel-title: "チャンネルのタイトル"
mk-channel-form: common/views/widgets/server.vue:
textarea: "書いて" title: "サーバー情報"
upload: "アップロード" toggle: "表示を切り替え"
drive: "ドライブ"
note: "やる"
posting: "やってます"
desktop: desktop/views/components/activity.vue:
tags: title: "アクティビティ"
mk-api-info: toggle: "表示を切り替え"
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
regenerate-token: "トークンを再生成"
enter-password: "パスワードを入力してください"
mk-drive-browser-base-contextmenu: desktop/views/components/calendar.vue:
create-folder: "フォルダーを作成" title: "{1}年 {2}月"
upload: "ファイルをアップロード" prev: "前の月"
url-upload: "URLからアップロード" next: "次の月"
go: "クリックして時間遡行"
mk-drive-browser-window: desktop/views/components/drive-window.vue:
used: "使用中" used: "使用中"
drive: "ドライブ" drive: "ドライブ"
mk-drive-browser: desktop/views/components/drive.file.vue:
avatar: "アイコン"
banner: "バナー"
contextmenu:
rename: "名前を変更"
copy-url: "URLをコピー"
download: "ダウンロード"
else-files: "その他..."
set-as-avatar: "アイコンに設定"
set-as-banner: "バナーに設定"
open-in-app: "アプリで開く"
add-app: "アプリを追加"
rename-file: "ファイル名の変更"
input-new-file-name: "新しいファイル名を入力してください"
copied: "コピー完了"
copied-url-to-clipboard: "URLをクリップボードにコピーしました"
desktop/views/components/drive.folder.vue:
unable-to-process: "操作を完了できません"
circular-reference-detected: "移動先のフォルダーは、移動するフォルダーのサブフォルダーです。"
unhandled-error: "不明なエラー"
contextmenu:
move-to-this-folder: "このフォルダへ移動"
show-in-new-window: "新しいウィンドウで表示"
rename: "名前を変更"
rename-folder: "フォルダ名の変更"
input-new-folder-name: "新しいフォルダ名を入力してください"
desktop/views/components/drive.nav-folder.vue:
drive: "ドライブ"
desktop/views/components/drive.vue:
search: "検索" search: "検索"
load-more: "もっと読み込む" load-more: "もっと読み込む"
empty-draghover: "ドロップですか?いいですよ、ボクはカワイイですからね" empty-draghover: "ドロップですか?いいですよ、ボクはカワイイですからね"
@ -248,108 +243,26 @@ desktop:
may-take-time: "アップロードが完了するまで時間がかかる場合があります。" may-take-time: "アップロードが完了するまで時間がかかる場合があります。"
create-folder: "フォルダー作成" create-folder: "フォルダー作成"
folder-name: "フォルダー名" folder-name: "フォルダー名"
contextmenu:
create-folder: "フォルダーを作成"
upload: "ファイルをアップロード"
url-upload: "URLからアップロード"
mk-drive-browser-file-contextmenu: desktop/views/components/messaging-window.vue:
rename: "名前を変更" title: "メッセージ"
copy-url: "URLをコピー"
download: "ダウンロード"
else-files: "その他..."
set-as-avatar: "アバターに設定"
set-as-banner: "バナーに設定"
open-in-app: "アプリで開く"
add-app: "アプリを追加"
rename-file: "ファイル名の変更"
input-new-file-name: "新しいファイル名を入力してください"
copied: "コピー完了"
copied-url-to-clipboard: "URLをクリップボードにコピーしました"
mk-drive-browser-file: desktop/views/components/notes.note.vue:
avatar: "アバター" reposted-by: "{}がRenote"
banner: "バナー" reply: "返信"
renote: "Renote"
add-reaction: "リアクション"
detail: "詳細"
mk-drive-browser-folder-contextmenu: desktop/views/components/notifications.vue:
move-to-this-folder: "このフォルダへ移動" more: "もっと見る"
show-in-new-window: "新しいウィンドウで表示" empty: "ありません!"
rename: "名前を変更"
rename-folder: "フォルダ名の変更"
input-new-folder-name: "新しいフォルダ名を入力してください"
mk-drive-browser-folder: desktop/views/components/post-form.vue:
unable-to-process: "操作を完了できません"
circular-reference-detected: "移動先のフォルダーは、移動するフォルダーのサブフォルダーです。"
unhandled-error: "不明なエラー"
mk-drive-browser-nav-folder:
drive: "ドライブ"
mk-selectdrive-page:
title: "ファイルを選択してください"
ok: "決定"
cancel: "キャンセル"
upload: "PCからドライブにファイルをアップロード"
mk-ui-header-nav:
home: "ホーム"
messaging: "メッセージ"
ch: "チャンネル"
info: "お知らせ"
mk-ui-header-search:
placeholder: "検索"
mk-ui-header-account:
profile: "プロフィール"
drive: "ドライブ"
mentions: "あなた宛て"
settings: "設定"
signout: "サインアウト"
mk-ui-header-note-button:
note: "新規投稿"
mk-ui-header-notifications:
title: "通知"
mk-profile-setting:
avatar: "アバター"
choice-avatar: "画像を選択"
name: "名前"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
save: "保存"
mk-password-setting:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
mk-2fa-setting:
intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。"
detail: "詳細..."
url: "https://www.google.co.jp/intl/ja/landing/2step/"
caution: "登録したデバイスを紛失するなどした場合、Misskeyにサインインできなくなりますのでご注意ください。"
register: "デバイスを登録する"
already-registered: "既に設定は完了しています。"
unregister: "設定を解除"
unregistered: "二段階認証が無効になりました。"
enter-password: "パスワードを入力してください"
authenticator: "まず、Google Authenticatorをお使いのデバイスにインストールします:"
howtoinstall: "インストール方法はこちら"
scan: "次に、表示されているQRコードをスキャンします:"
done: "お使いのデバイスに表示されているトークンを入力して完了します:"
submit: "完了"
success: "設定が完了しました!"
failed: "設定に失敗しました。トークンに誤りがないかご確認ください。"
info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。"
mk-mute-setting:
no-users: "ミュートしているユーザーはいません"
mk-post-form:
note-placeholder: "いまどうしてる?" note-placeholder: "いまどうしてる?"
reply-placeholder: "この投稿への返信..." reply-placeholder: "この投稿への返信..."
quote-placeholder: "この投稿を引用..." quote-placeholder: "この投稿を引用..."
@ -368,20 +281,29 @@ desktop:
attach-cancel: "添付取り消し" attach-cancel: "添付取り消し"
insert-a-kao: "v(‘ω’)v" insert-a-kao: "v(‘ω’)v"
create-poll: "投票を作成" create-poll: "投票を作成"
text-remain: "のこり{}文字" text-remain: "り{}文字"
mk-post-form-window: desktop/views/components/post-form-window.vue:
note: "新規投稿" note: "新規投稿"
reply: "返信" reply: "返信"
attaches: "添付: {}メディア" attaches: "添付: {}メディア"
uploading-media: "{}個のメディアをアップロード中" uploading-media: "{}個のメディアをアップロード中"
mk-note-page: desktop/views/components/renote-form.vue:
prev: "前の投稿" quote: "引用する..."
next: "次の投稿" cancel: "キャンセル"
renote: "Renote"
reposting: "しています..."
success: "Renoteしました"
failure: "Renoteに失敗しました"
mk-settings: desktop/views/components/renote-form-window.vue:
title: "この投稿をRenoteしますか"
desktop/views/components/settings.vue:
profile: "プロフィール" profile: "プロフィール"
notification: "通知"
apps: "アプリ"
mute: "ミュート" mute: "ミュート"
drive: "ドライブ" drive: "ドライブ"
security: "セキュリティ" security: "セキュリティ"
@ -390,208 +312,144 @@ desktop:
other: "その他" other: "その他"
license: "ライセンス" license: "ライセンス"
mk-timeline-note: desktop/views/components/settings.2fa.vue:
reposted-by: "{}がRenote" intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。"
reply: "返信" detail: "詳細..."
renote: "Renote" url: "https://www.google.co.jp/intl/ja/landing/2step/"
add-reaction: "リアクション" caution: "登録したデバイスを紛失するなどした場合、Misskeyにサインインできなくなりますのでご注意ください。"
detail: "詳細" register: "デバイスを登録する"
already-registered: "既に設定は完了しています。"
unregister: "設定を解除"
unregistered: "二段階認証が無効になりました。"
enter-password: "パスワードを入力してください"
authenticator: "まず、Google Authenticatorをお使いのデバイスにインストールします:"
howtoinstall: "インストール方法はこちら"
scan: "次に、表示されているQRコードをスキャンします:"
done: "お使いのデバイスに表示されているトークンを入力して完了します:"
submit: "完了"
success: "設定が完了しました!"
failed: "設定に失敗しました。トークンに誤りがないかご確認ください。"
info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。"
mk-notifications: desktop/views/components/settings.api.vue:
more: "もっと見る" intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
regenerate-token: "トークンを再生成"
enter-password: "パスワードを入力してください"
mk-notifications-home-widget: desktop/views/components/settings.app.vue:
no-apps: "連携しているアプリケーションはありません"
desktop/views/components/settings.mute.vue:
no-users: "ミュートしているユーザーはいません"
desktop/views/components/settings.password.vue:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/settings.profile.vue:
avatar: "アイコン"
choice-avatar: "画像を選択"
name: "名前"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
save: "保存"
desktop/views/components/ui.header.account.vue:
profile: "プロフィール"
drive: "ドライブ"
mentions: "あなた宛て"
customize: "カスタマイズ"
settings: "設定"
signout: "サインアウト"
desktop/views/components/ui.header.nav.vue:
home: "ホーム"
messaging: "メッセージ"
game: "ゲーム"
desktop/views/components/ui.header.notifications.vue:
title: "通知" title: "通知"
settings: "通知の設定"
mk-server-home-widget: desktop/views/components/ui.header.post.vue:
title: "サーバー情報" post: "新規投稿"
toggle: "表示を切り替え"
mk-activity-widget: desktop/views/components/ui.header.search.vue:
title: "アクティビティ" placeholder: "検索"
toggle: "表示を切り替え"
mk-user-recommendation-home-widget: desktop/views/pages/note.vue:
title: "おすすめユーザー" prev: "前の投稿"
refresh: "他を見る" next: "次の投稿"
no-one: "いません!"
mk-recommended-polls-home-widget: desktop/views/pages/selectdrive.vue:
title: "投票" title: "ファイルを選択してください"
refresh: "他を見る" ok: "決定"
nothing: "ありません!"
mk-trends-home-widget:
title: "トレンド"
refresh: "他を見る"
nothing: "ありません!"
mk-photo-stream-home-widget:
title: "フォトストリーム"
no-photos: "写真はありません"
mk-donation-home-widget:
title: "寄付のお願い"
text: "Misskeyの運営にはドメイン、サーバー等のコストが掛かります。Misskeyは広告を掲載したりしないため、収入を皆様からの寄付に頼っています。もしご興味があれば、{}までご連絡ください。ご協力ありがとうございます。"
mk-channel-home-widget:
title: "チャンネル"
settings: "ウィジェットの設定"
get-started: "右上の歯車をクリックして受信するチャンネルを指定してください"
mk-calendar-widget:
title: "{1}年 {2}月"
prev: "前の月"
next: "次の月"
go: "クリックして時間遡行"
mk-post-form-home-widget:
title: "投稿"
note: "投稿"
placeholder: "いまどうしてる?"
mk-access-log-home-widget:
title: "アクセスログ"
mk-messaging-home-widget:
title: "メッセージ"
mk-broadcast-home-widget:
fetching: "確認中"
no-broadcasts: "お知らせはありません"
have-a-nice-day: "良い一日を!"
next: "次"
mk-renote-form:
quote: "引用する..."
cancel: "キャンセル" cancel: "キャンセル"
renote: "Renote" upload: "PCからドライブにファイルをアップロード"
reposting: "しています..."
success: "Renoteしました"
failure: "Renoteに失敗しました"
mk-renote-form-window: desktop/views/pages/user/user.followers-you-know.vue:
title: "この投稿をRenoteしますか" title: "知り合いのフォロワー"
loading: "読み込み中"
no-users: "知り合いのフォロワーはいません"
mk-user: desktop/views/pages/user/user.friends.vue:
title: "よく話すユーザー"
loading: "読み込み中"
no-users: "よく話すユーザーはいません"
desktop/views/pages/user/user.home.vue:
last-used-at: "最終アクセス" last-used-at: "最終アクセス"
desktop/views/pages/user/user.photos.vue:
title: "フォト"
loading: "読み込み中"
no-photos: "写真はありません"
desktop/views/pages/user/user.profile.vue:
follows-you: "フォローされています" follows-you: "フォローされています"
mute: "ミュートする" mute: "ミュートする"
muted: "ミュートしています" muted: "ミュートしています"
unmute: "ミュート解除" unmute: "ミュート解除"
photos: desktop/views/widgets/messaging.vue:
title: "フォト" title: "メッセージ"
loading: "読み込み中"
no-photos: "写真はありません"
frequently-replied-users: desktop/views/widgets/notifications.vue:
title: "よく話すユーザー" title: "通知"
loading: "読み込み中" settings: "通知の設定"
no-users: "よく話すユーザーはいません"
followers-you-know: desktop/views/widgets/polls.vue:
title: "知り合いのフォロワー" title: "投票"
loading: "読み込み中" refresh: "他を見る"
no-users: "知り合いのフォロワーはいません" nothing: "ありません!"
mobile: desktop/views/widgets/post-form.vue:
tags:
mk-selectdrive-page:
select-file: "ファイルを選択"
mk-drive-file-viewer:
download: "ダウンロード"
rename: "名前を変更"
move: "移動"
hash: "ハッシュ (md5)"
exif: "EXIF"
mk-entrance-signin:
signup: "新規登録"
about: "Misskeyについて"
mk-entrance-signup:
cancel: "キャンセル"
mk-authorized-apps-page:
application: "アプリケーション"
mk-signin-history-page:
signin-history: "ログイン履歴"
mk-twitter-setting-page:
twitter-integration: "Twitter連携"
mk-drive-page:
drive: "ドライブ"
mk-home:
home: "ホーム"
mk-messaging-room-page:
message: "メッセージ"
mk-messaging-page:
message: "メッセージ"
mk-notifications-page:
notifications: "通知"
read-all: "すべての通知を既読にしますか?"
mk-note-page:
title: "投稿" title: "投稿"
prev: "前の投稿" note: "投稿"
next: "次の投稿" placeholder: "いまどうしてる?"
mk-search-page: desktop/views/widgets/trends.vue:
search: "検索" title: "トレンド"
refresh: "他を見る"
nothing: "ありません!"
mk-settings: desktop/views/widgets/users.vue:
signed-in-as: "{}としてサインイン中" title: "おすすめユーザー"
refresh: "他を見る"
no-one: "いません!"
mk-settings-page: desktop/views/widgets/channel.vue:
profile: "プロフィール" title: "チャンネル"
applications: "アプリケーション" settings: "ウィジェットの設定"
twitter-integration: "Twitter連携" get-started: "右上の歯車をクリックして受信するチャンネルを指定してください"
signin-history: "サインイン履歴"
link: "Misskeyリンク"
settings: "設定"
signout: "サインアウト"
mk-profile-setting-page: mobile/views/components/drive.vue:
title: "プロフィール設定"
mk-profile-setting:
will-be-published: "これらのプロフィールは公開されます。"
name: "名前"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アバター"
banner: "バナー"
avatar-saved: "アバターを保存しました"
banner-saved: "バナーを保存しました"
set-avatar: "アバターを選択する"
set-banner: "バナーを選択する"
save: "保存"
saved: "プロフィールを保存しました"
mk-user-followers-page:
followers-of: "{}のフォロワー"
mk-user-following-page:
following-of: "{}のフォロー"
mk-drive-folder-selector:
select-folder: "フォルダーを選択"
mk-drive-selector:
select-file: "ファイルを選択"
mk-drive:
drive: "ドライブ" drive: "ドライブ"
used: "使用中" used: "使用中"
folder-count: "フォルダ" folder-count: "フォルダ"
@ -601,62 +459,125 @@ mobile:
nothing-in-drive: "ドライブには何もありません" nothing-in-drive: "ドライブには何もありません"
folder-is-empty: "このフォルダは空です" folder-is-empty: "このフォルダは空です"
mk-follow-button: mobile/views/components/drive-file-chooser.vue:
select-file: "ファイルを選択"
mobile/views/components/drive-folder-chooser.vue:
select-folder: "フォルダーを選択"
mobile/views/components/drive.file-detail.vue:
download: "ダウンロード"
rename: "名前を変更"
move: "移動"
hash: "ハッシュ (md5)"
exif: "EXIF"
mobile/views/components/follow-button.vue:
follow: "フォロー" follow: "フォロー"
unfollow: "フォロー解除" unfollow: "フォロー解除"
mk-home-timeline: mobile/views/components/note.vue:
empty-timeline: "表示する投稿がありません。誰かしらをフォローするなどしましょう。" reposted-by: "{}がRenote"
mk-notifications: mobile/views/components/note-detail.vue:
more: "もっと見る"
empty: "ありません!"
mk-note-detail:
reply: "返信" reply: "返信"
reaction: "リアクション" reaction: "リアクション"
mk-post-form: mobile/views/components/notifications.vue:
more: "もっと見る"
empty: "ありません!"
mobile/views/components/post-form.vue:
submit: "投稿" submit: "投稿"
reply-placeholder: "この投稿への返信..." reply-placeholder: "この投稿への返信..."
note-placeholder: "いまどうしてる?" note-placeholder: "いまどうしてる?"
mk-search-notes: mobile/views/components/sub-note-content.vue:
empty: "「{}」に関する投稿は見つかりませんでした。"
mk-sub-note-content:
media-count: "{}個のメディア" media-count: "{}個のメディア"
poll: "投票" poll: "投票"
mk-timeline-note: mobile/views/components/timeline.vue:
reposted-by: "{}がRenote" empty: "投稿がありません"
load-more: "もっと"
mk-timeline: mobile/views/components/ui.nav.vue:
empty: "表示するものがありません"
load-more: "もっとみる"
mk-ui-nav:
home: "ホーム" home: "ホーム"
notifications: "通知" notifications: "通知"
messaging: "メッセージ" messaging: "メッセージ"
ch: "チャンネル"
search: "検索" search: "検索"
drive: "ドライブ" drive: "ドライブ"
settings: "設定" settings: "設定"
about: "Misskeyについて" about: "Misskeyについて"
mk-user-followers: mobile/views/components/user-timeline.vue:
no-users: "フォロワーはいないようです。" no-notes: "このユーザーは投稿していないようです。"
mk-user-following:
no-users: "フォロー中のユーザーはいないようです。"
mk-user-timeline:
no-notes: "このユーザーはまだ投稿していないようです。"
no-notes-with-media: "メディア付き投稿はありません。" no-notes-with-media: "メディア付き投稿はありません。"
load-more: "もっとみる" load-more: "もっと"
mk-user: mobile/views/components/users-list.vue:
all: "すべて"
known: "知り合い"
load-more: "もっと"
mobile/views/pages/drive.vue:
drive: "ドライブ"
mobile/views/pages/followers.vue:
followers-of: "{}のフォロワー"
mobile/views/pages/following.vue:
following-of: "{}のフォロー"
mobile/views/pages/home.vue:
timeline: "タイムライン"
mobile/views/pages/messaging.vue:
messaging: "メッセージ"
mobile/views/pages/messaging-room.vue:
messaging: "メッセージ"
mobile/views/pages/note.vue:
title: "投稿"
prev: "前の投稿"
next: "次の投稿"
mobile/views/pages/notifications.vue:
notifications: "通知"
read-all: "すべての通知を既読にしますか?"
mobile/views/pages/profile-setting.vue:
title: "プロフィール設定"
will-be-published: "これらのプロフィールは公開されます。"
name: "名前"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
avatar-saved: "アイコンを保存しました"
banner-saved: "バナーを保存しました"
set-avatar: "アイコンを選択する"
set-banner: "バナーを選択する"
save: "保存"
saved: "プロフィールを保存しました"
mobile/views/pages/search.vue:
search: "検索"
empty: "「{}」に関する投稿は見つかりませんでした。"
mobile/views/pages/selectdrive.vue:
select-file: "ファイルを選択"
mobile/views/pages/settings.vue:
signed-in-as: "{}としてサインイン中"
profile: "プロフィール"
twitter: "Twitter連携"
signin-history: "サインイン履歴"
settings: "設定"
signout: "サインアウト"
mobile/views/pages/user.vue:
follows-you: "フォローされています" follows-you: "フォローされています"
following: "フォロー" following: "フォロー"
followers: "フォロワー" followers: "フォロワー"
@ -665,7 +586,7 @@ mobile:
timeline: "タイムライン" timeline: "タイムライン"
media: "メディア" media: "メディア"
mk-user-overview: mobile/views/pages/user/home.vue:
recent-notes: "最近の投稿" recent-notes: "最近の投稿"
images: "画像" images: "画像"
activity: "アクティビティ" activity: "アクティビティ"
@ -675,37 +596,36 @@ mobile:
followers-you-know: "知り合いのフォロワー" followers-you-know: "知り合いのフォロワー"
last-used-at: "最終ログイン" last-used-at: "最終ログイン"
mk-user-overview-notes: mobile/views/pages/user/home.followers-you-know.vue:
loading: "読み込み中"
no-notes: "投稿はありません"
mk-user-overview-photos:
loading: "読み込み中"
no-photos: "写真はありません"
mk-user-overview-keywords:
no-keywords: "キーワードはありません(十分な数の投稿をしていない可能性があります)"
mk-user-overview-domains:
no-domains: "よく表れるドメインは検出されませんでした"
mk-user-overview-frequently-replied-users:
loading: "読み込み中"
no-users: "よく会話するユーザーはいません"
mk-user-overview-followers-you-know:
loading: "読み込み中" loading: "読み込み中"
no-users: "知り合いのユーザーはいません" no-users: "知り合いのユーザーはいません"
mk-users-list: mobile/views/pages/user/home.friends.vue:
all: "すべて" loading: "読み込み中"
known: "知り合い" no-users: "よく会話するユーザーはいません"
load-more: "もっと"
stats: mobile/views/pages/user/home.notes.vue:
notes-count: "投稿の数" loading: "読み込み中"
users-count: "アカウントの数" no-notes: "投稿はありません"
status: mobile/views/pages/user/home.photos.vue:
all-systems-maybe-operational: "すべてのシステムがたぶん正常に作動しています" loading: "読み込み中"
what-is-this-site: "" no-photos: "写真はありません"
docs:
edit-this-page-on-github: "間違いや改善点を見つけましたか?"
edit-this-page-on-github-link: "このページをGitHubで編集"
api:
entities:
properties: "プロパティ"
endpoints:
params: "パラメータ"
res: "レスポンス"
props:
name: "名前"
type: "型"
optional: "オプション"
description: "説明"
yes: "はい"
no: "いいえ"

View file

View file

@ -1,7 +1,7 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <i@syuilo.com>", "author": "syuilo <i@syuilo.com>",
"version": "0.0.4771", "version": "0.0.4876",
"codename": "nighthike", "codename": "nighthike",
"license": "MIT", "license": "MIT",
"description": "A miniblog-based SNS", "description": "A miniblog-based SNS",
@ -10,7 +10,7 @@
"main": "./built/index.js", "main": "./built/index.js",
"private": true, "private": true,
"scripts": { "scripts": {
"config": "node ./tools/init.js", "config": "node ./cli/init.js",
"start": "node ./built", "start": "node ./built",
"debug": "DEBUG=misskey:* node ./built", "debug": "DEBUG=misskey:* node ./built",
"swagger": "node ./swagger.js", "swagger": "node ./swagger.js",
@ -140,6 +140,7 @@
"koa-bodyparser": "4.2.0", "koa-bodyparser": "4.2.0",
"koa-compress": "^2.0.0", "koa-compress": "^2.0.0",
"koa-favicon": "2.0.1", "koa-favicon": "2.0.1",
"koa-json-body": "^5.3.0",
"koa-mount": "3.0.0", "koa-mount": "3.0.0",
"koa-multer": "1.0.2", "koa-multer": "1.0.2",
"koa-router": "7.4.0", "koa-router": "7.4.0",

View file

@ -14,7 +14,7 @@ fontawesome.library.add(brands);
export const pattern = /%fa:(.+?)%/g; export const pattern = /%fa:(.+?)%/g;
export const replacement = (_, key) => { export const replacement = (match, key) => {
const args = key.split(' '); const args = key.split(' ');
let prefix = 'fas'; let prefix = 'fas';
const classes = []; const classes = [];

View file

@ -16,7 +16,7 @@ export default class Replacer {
this.replacement = this.replacement.bind(this); this.replacement = this.replacement.bind(this);
} }
private get(key: string) { private get(path: string, key: string) {
const texts = locale[this.lang]; const texts = locale[this.lang];
if (texts == null) { if (texts == null) {
@ -26,6 +26,15 @@ export default class Replacer {
let text = texts; let text = texts;
if (path) {
if (text.hasOwnProperty(path)) {
text = text[path];
} else {
console.warn(`path '${path}' not found in '${this.lang}'`);
return key; // Fallback
}
}
// Check the key existance // Check the key existance
const error = key.split('.').some(k => { const error = key.split('.').some(k => {
if (text.hasOwnProperty(k)) { if (text.hasOwnProperty(k)) {
@ -37,21 +46,31 @@ export default class Replacer {
}); });
if (error) { if (error) {
console.warn(`key '${key}' not found in '${this.lang}'`); console.warn(`key '${key}' not found in '${path}' of '${this.lang}'`);
return key; // Fallback return key; // Fallback
} else { } else {
return text; return text;
} }
} }
public replacement(match, a, b, c) { public replacement(ctx, match, a, b, c) {
const key = a || b || c; const client = 'misskey/src/client/app/';
let name = null;
let key = a || b || c;
if (key[0] == '@') {
name = ctx.src.substr(ctx.src.indexOf(client) + client.length);
key = key.substr(1);
}
if (ctx && ctx.lang) this.lang = ctx.lang;
if (match[0] == '"') { if (match[0] == '"') {
return '"' + this.get(key).replace(/"/g, '\\"') + '"'; return '"' + this.get(name, key).replace(/"/g, '\\"') + '"';
} else if (match[0] == "'") { } else if (match[0] == "'") {
return '\'' + this.get(key).replace(/'/g, '\\\'') + '\''; return '\'' + this.get(name, key).replace(/'/g, '\\\'') + '\'';
} else { } else {
return this.get(key); return this.get(name, key);
} }
} }
} }

View file

@ -30,11 +30,10 @@
//#endregion //#endregion
// Detect the user language // Detect the user language
// Note: The default language is English // Note: The default language is Japanese
let lang = navigator.language.split('-')[0]; let lang = navigator.language.split('-')[0];
if (!/^(en|ja)$/.test(lang)) lang = 'en'; if (!/^(en|ja)$/.test(lang)) lang = 'ja';
if (localStorage.getItem('lang')) lang = localStorage.getItem('lang'); if (localStorage.getItem('lang')) lang = localStorage.getItem('lang');
if (ENV != 'production') lang = 'ja';
// Detect the user agent // Detect the user agent
const ua = navigator.userAgent.toLowerCase(); const ua = navigator.userAgent.toLowerCase();
@ -80,7 +79,7 @@
script.setAttribute('defer', 'true'); script.setAttribute('defer', 'true');
head.appendChild(script); head.appendChild(script);
// 1秒経ってもスクリプトがロードされない場合はバージョンが古くて // 3秒経ってもスクリプトがロードされない場合はバージョンが古くて
// 404になっているせいかもしれないので、バージョンを確認して古ければ更新する // 404になっているせいかもしれないので、バージョンを確認して古ければ更新する
// //
// 読み込まれたスクリプトからこのタイマーを解除できるように、 // 読み込まれたスクリプトからこのタイマーを解除できるように、
@ -118,5 +117,5 @@
// Force reload // Force reload
location.reload(true); location.reload(true);
} }
}, 1000); }, 3000);
} }

View file

@ -441,10 +441,11 @@ export default class MiOS extends EventEmitter {
document.body.appendChild(spinner); document.body.appendChild(spinner);
} }
// Append a credential const onFinally = () => {
if (this.isSignedIn) (data as any).i = this.i.token; if (--pending === 0) spinner.parentNode.removeChild(spinner);
};
return new Promise((resolve, reject) => { const promise = new Promise((resolve, reject) => {
const viaStream = this.stream.hasConnection && const viaStream = this.stream.hasConnection &&
(localStorage.getItem('apiViaStream') ? localStorage.getItem('apiViaStream') == 'true' : true); (localStorage.getItem('apiViaStream') ? localStorage.getItem('apiViaStream') == 'true' : true);
@ -453,9 +454,9 @@ export default class MiOS extends EventEmitter {
const id = Math.random().toString(); const id = Math.random().toString();
stream.once(`api-res:${id}`, res => { stream.once(`api-res:${id}`, res => {
if (--pending === 0) spinner.parentNode.removeChild(spinner); if (res == null || Object.keys(res).length == 0) {
resolve(null);
if (res.res) { } else if (res.res) {
resolve(res.res); resolve(res.res);
} else { } else {
reject(res.e); reject(res.e);
@ -469,6 +470,9 @@ export default class MiOS extends EventEmitter {
data data
}); });
} else { } else {
// Append a credential
if (this.isSignedIn) (data as any).i = this.i.token;
const req = { const req = {
id: uuid(), id: uuid(),
date: new Date(), date: new Date(),
@ -489,8 +493,6 @@ export default class MiOS extends EventEmitter {
credentials: endpoint === 'signin' ? 'include' : 'omit', credentials: endpoint === 'signin' ? 'include' : 'omit',
cache: 'no-cache' cache: 'no-cache'
}).then(async (res) => { }).then(async (res) => {
if (--pending === 0) spinner.parentNode.removeChild(spinner);
const body = res.status === 204 ? null : await res.json(); const body = res.status === 204 ? null : await res.json();
if (this.debug) { if (this.debug) {
@ -508,6 +510,10 @@ export default class MiOS extends EventEmitter {
}).catch(reject); }).catch(reject);
} }
}); });
promise.then(onFinally, onFinally);
return promise;
} }
/** /**

View file

@ -1,34 +1,34 @@
<template> <template>
<div class="troubleshooter"> <div class="troubleshooter">
<h1>%fa:wrench%%i18n:common.tags.mk-error.troubleshooter.title%</h1> <h1>%fa:wrench%%i18n:@title%</h1>
<div> <div>
<p :data-wip="network == null"> <p :data-wip="network == null">
<template v-if="network != null"> <template v-if="network != null">
<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:common.tags.mk-error.troubleshooter.checking-network%' : '%i18n:common.tags.mk-error.troubleshooter.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:common.tags.mk-error.troubleshooter.checking-internet%' : '%i18n:common.tags.mk-error.troubleshooter.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:common.tags.mk-error.troubleshooter.checking-server%' : '%i18n:common.tags.mk-error.troubleshooter.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:common.tags.mk-error.troubleshooter.finding%<mk-ellipsis/></p> <p v-if="!end">%i18n:@finding%<mk-ellipsis/></p>
<p v-if="network === false"><b>%fa:exclamation-triangle%%i18n:common.tags.mk-error.troubleshooter.no-network%</b><br>%i18n:common.tags.mk-error.troubleshooter.no-network-desc%</p> <p v-if="network === false"><b>%fa:exclamation-triangle%%i18n:@no-network%</b><br>%i18n:@no-network-desc%</p>
<p v-if="internet === false"><b>%fa:exclamation-triangle%%i18n:common.tags.mk-error.troubleshooter.no-internet%</b><br>%i18n:common.tags.mk-error.troubleshooter.no-internet-desc%</p> <p v-if="internet === false"><b>%fa:exclamation-triangle%%i18n:@no-internet%</b><br>%i18n:@no-internet-desc%</p>
<p v-if="server === false"><b>%fa:exclamation-triangle%%i18n:common.tags.mk-error.troubleshooter.no-server%</b><br>%i18n:common.tags.mk-error.troubleshooter.no-server-desc%</p> <p v-if="server === false"><b>%fa:exclamation-triangle%%i18n:@no-server%</b><br>%i18n:@no-server-desc%</p>
<p v-if="server === true" class="success"><b>%fa:info-circle%%i18n:common.tags.mk-error.troubleshooter.success%</b><br>%i18n:common.tags.mk-error.troubleshooter.success-desc%</p> <p v-if="server === true" class="success"><b>%fa:info-circle%%i18n:@success%</b><br>%i18n:@success-desc%</p>
</div> </div>
</template> </template>

View file

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

View file

@ -1,5 +1,5 @@
<template> <template>
<a class="a" href="https://github.com/syuilo/misskey" target="_blank" title="%i18n:common.tags.mk-forkit.open-github-link%" aria-label="%i18n:common.tags.mk-forkit.open-github-link%"> <a class="a" href="https://github.com/syuilo/misskey" target="_blank" title="View source on Github">
<svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="aria-hidden"> <svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="aria-hidden">
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path> <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
<path class="octo-arm" d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor"></path> <path class="octo-arm" d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor"></path>

View file

@ -8,18 +8,18 @@
ref="textarea" ref="textarea"
@keypress="onKeypress" @keypress="onKeypress"
@paste="onPaste" @paste="onPaste"
placeholder="%i18n:common.input-message-here%" placeholder="%i18n:@input-message-here%"
v-autocomplete="'text'" v-autocomplete="'text'"
></textarea> ></textarea>
<div class="file" @click="file = null" v-if="file">{{ file.name }}</div> <div class="file" @click="file = null" v-if="file">{{ file.name }}</div>
<mk-uploader ref="uploader" @uploaded="onUploaded"/> <mk-uploader ref="uploader" @uploaded="onUploaded"/>
<button class="send" @click="send" :disabled="!canSend || sending" title="%i18n:common.send%"> <button class="send" @click="send" :disabled="!canSend || sending" title="%i18n:@send%">
<template v-if="!sending">%fa:paper-plane%</template><template v-if="sending">%fa:spinner .spin%</template> <template v-if="!sending">%fa:paper-plane%</template><template v-if="sending">%fa:spinner .spin%</template>
</button> </button>
<button class="attach-from-local" @click="chooseFile" title="%i18n:common.tags.mk-messaging-form.attach-from-local%"> <button class="attach-from-local" @click="chooseFile" title="%i18n:@attach-from-local%">
%fa:upload% %fa:upload%
</button> </button>
<button class="attach-from-drive" @click="chooseFileFromDrive" title="%i18n:common.tags.mk-messaging-form.attach-from-drive%"> <button class="attach-from-drive" @click="chooseFileFromDrive" title="%i18n:@attach-from-drive%">
%fa:R folder-open% %fa:R folder-open%
</button> </button>
<input ref="file" type="file" @change="onChangeFile"/> <input ref="file" type="file" @change="onChangeFile"/>

View file

@ -5,7 +5,7 @@
</router-link> </router-link>
<div class="content"> <div class="content">
<div class="balloon" :data-no-text="message.text == null"> <div class="balloon" :data-no-text="message.text == null">
<p class="read" v-if="isMe && message.isRead">%i18n:common.tags.mk-messaging-message.is-read%</p> <p class="read" v-if="isMe && message.isRead">%i18n:@is-read%</p>
<button class="delete-button" v-if="isMe" title="%i18n:common.delete%"> <button class="delete-button" v-if="isMe" title="%i18n:common.delete%">
<img src="/assets/desktop/messaging/delete.png" alt="Delete"/> <img src="/assets/desktop/messaging/delete.png" alt="Delete"/>
</button> </button>
@ -19,7 +19,7 @@
</div> </div>
</div> </div>
<div class="content" v-if="message.isDeleted"> <div class="content" v-if="message.isDeleted">
<p class="is-deleted">%i18n:common.tags.mk-messaging-message.deleted%</p> <p class="is-deleted">%i18n:@deleted%</p>
</div> </div>
</div> </div>
<div></div> <div></div>

View file

@ -5,10 +5,10 @@
> >
<div class="stream"> <div class="stream">
<p class="init" v-if="init">%fa:spinner .spin%%i18n:common.loading%</p> <p class="init" v-if="init">%fa:spinner .spin%%i18n:common.loading%</p>
<p class="empty" v-if="!init && messages.length == 0">%fa:info-circle%%i18n:common.tags.mk-messaging-room.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:common.tags.mk-messaging-room.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:common.tags.mk-messaging-room.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"/>
@ -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:common.tags.mk-messaging-room.new-message%'); this.notify('%i18n:@new-message%');
} }
}, },

View file

@ -3,7 +3,7 @@
<div class="search" v-if="!compact" :style="{ top: headerTop + 'px' }"> <div class="search" v-if="!compact" :style="{ top: headerTop + 'px' }">
<div class="form"> <div class="form">
<label for="search-input">%fa:search%</label> <label for="search-input">%fa:search%</label>
<input v-model="q" type="search" @input="search" @keydown="onSearchKeydown" placeholder="%i18n:common.tags.mk-messaging.search-user%"/> <input v-model="q" type="search" @input="search" @keydown="onSearchKeydown" placeholder="%i18n:@search-user%"/>
</div> </div>
<div class="result"> <div class="result">
<ol class="users" v-if="result.length > 0" ref="searchResult"> <ol class="users" v-if="result.length > 0" ref="searchResult">
@ -38,13 +38,13 @@
<mk-time :time="message.createdAt"/> <mk-time :time="message.createdAt"/>
</header> </header>
<div class="body"> <div class="body">
<p class="text"><span class="me" v-if="isMe(message)">%i18n:common.tags.mk-messaging.you%:</span>{{ message.text }}</p> <p class="text"><span class="me" v-if="isMe(message)">%i18n:@you%:</span>{{ message.text }}</p>
</div> </div>
</div> </div>
</a> </a>
</template> </template>
</div> </div>
<p class="no-history" v-if="!fetching && messages.length == 0">%i18n:common.tags.mk-messaging.no-history%</p> <p class="no-history" v-if="!fetching && messages.length == 0">%i18n:@no-history%</p>
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p> <p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
</div> </div>
</template> </template>

View file

@ -1,18 +1,18 @@
<template> <template>
<span class="mk-nav"> <span class="mk-nav">
<a :href="aboutUrl">%i18n:common.tags.mk-nav-links.about%</a> <a :href="aboutUrl">%i18n:@about%</a>
<i></i> <i></i>
<a :href="statsUrl">%i18n:common.tags.mk-nav-links.stats%</a> <a :href="statsUrl">%i18n:@stats%</a>
<i></i> <i></i>
<a :href="statusUrl">%i18n:common.tags.mk-nav-links.status%</a> <a :href="statusUrl">%i18n:@status%</a>
<i></i> <i></i>
<a href="http://zawazawa.jp/misskey/">%i18n:common.tags.mk-nav-links.wiki%</a> <a href="http://zawazawa.jp/misskey/">%i18n:@wiki%</a>
<i></i> <i></i>
<a href="https://github.com/syuilo/misskey/blob/master/DONORS.md">%i18n:common.tags.mk-nav-links.donors%</a> <a href="https://github.com/syuilo/misskey/blob/master/DONORS.md">%i18n:@donors%</a>
<i></i> <i></i>
<a href="https://github.com/syuilo/misskey">%i18n:common.tags.mk-nav-links.repository%</a> <a href="https://github.com/syuilo/misskey">%i18n:@repository%</a>
<i></i> <i></i>
<a :href="devUrl">%i18n:common.tags.mk-nav-links.develop%</a> <a :href="devUrl">%i18n:@develop%</a>
<i></i> <i></i>
<a href="https://twitter.com/misskey_xyz" target="_blank">Follow us on %fa:B twitter%</a> <a href="https://twitter.com/misskey_xyz" target="_blank">Follow us on %fa:B twitter%</a>
</span> </span>

View file

@ -2,7 +2,7 @@
<div class="mk-note-menu"> <div class="mk-note-menu">
<div class="backdrop" ref="backdrop" @click="close"></div> <div class="backdrop" ref="backdrop" @click="close"></div>
<div class="popover" :class="{ compact }" ref="popover"> <div class="popover" :class="{ compact }" ref="popover">
<button v-if="note.userId == os.i.id" @click="pin">%i18n:common.tags.mk-note-menu.pin%</button> <button v-if="note.userId == os.i.id" @click="pin">%i18n:@pin%</button>
</div> </div>
</div> </div>
</template> </template>

View file

@ -1,18 +1,18 @@
<template> <template>
<div class="mk-poll-editor"> <div class="mk-poll-editor">
<p class="caution" v-if="choices.length < 2"> <p class="caution" v-if="choices.length < 2">
%fa:exclamation-triangle%%i18n:common.tags.mk-poll-editor.no-only-one-choice% %fa:exclamation-triangle%%i18n:@no-only-one-choice%
</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:common.tags.mk-poll-editor.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:common.tags.mk-poll-editor.remove%"> <button @click="remove(i)" title="%i18n:@remove%">
%fa:times% %fa:times%
</button> </button>
</li> </li>
</ul> </ul>
<button class="add" v-if="choices.length < 10" @click="add">%i18n:common.tags.mk-poll-editor.add%</button> <button class="add" v-if="choices.length < 10" @click="add">%i18n:@add%</button>
<button class="destroy" @click="destroy" title="%i18n:common.tags.mk-poll-editor.destroy%"> <button class="destroy" @click="destroy" title="%i18n:@destroy%">
%fa:times% %fa:times%
</button> </button>
</div> </div>

View file

@ -1,20 +1,20 @@
<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:common.tags.mk-poll.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:common.tags.mk-poll.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:common.tags.mk-poll.total-users%'.replace('{}', total) }}</span> <span>{{ '%i18n:@total-users%'.replace('{}', total) }}</span>
<span></span> <span></span>
<a v-if="!isVoted" @click="toggleShowResult">{{ showResult ? '%i18n:common.tags.mk-poll.vote%' : '%i18n:common.tags.mk-poll.show-result%' }}</a> <a v-if="!isVoted" @click="toggleShowResult">{{ showResult ? '%i18n:@vote%' : '%i18n:@show-result%' }}</a>
<span v-if="isVoted">%i18n:common.tags.mk-poll.voted%</span> <span v-if="isVoted">%i18n:@voted%</span>
</p> </p>
</div> </div>
</template> </template>

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:common.tags.mk-reaction-picker.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

@ -1,15 +1,15 @@
<template> <template>
<form class="mk-signin" :class="{ signing }" @submit.prevent="onSubmit"> <form class="mk-signin" :class="{ signing }" @submit.prevent="onSubmit">
<label class="user-name"> <label class="user-name">
<input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" placeholder="%i18n:common.tags.mk-signin.username%" autofocus required @change="onUsernameChange"/>%fa:at% <input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" placeholder="%i18n:@username%" autofocus required @change="onUsernameChange"/>%fa:at%
</label> </label>
<label class="password"> <label class="password">
<input v-model="password" type="password" placeholder="%i18n:common.tags.mk-signin.password%" required/>%fa:lock% <input v-model="password" type="password" placeholder="%i18n:@password%" required/>%fa:lock%
</label> </label>
<label class="token" v-if="user && user.twoFactorEnabled"> <label class="token" v-if="user && user.twoFactorEnabled">
<input v-model="token" type="number" placeholder="%i18n:common.tags.mk-signin.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:common.tags.mk-signin.signing-in%' : '%i18n:common.tags.mk-signin.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

@ -1,42 +1,42 @@
<template> <template>
<form class="mk-signup" @submit.prevent="onSubmit" autocomplete="off"> <form class="mk-signup" @submit.prevent="onSubmit" autocomplete="off">
<label class="username"> <label class="username">
<p class="caption">%fa:at%%i18n:common.tags.mk-signup.username%</p> <p class="caption">%fa:at%%i18n:@username%</p>
<input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" placeholder="a~z、A~Z、0~9、-" autocomplete="off" required @input="onChangeUsername"/> <input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" placeholder="a~z、A~Z、0~9、-" autocomplete="off" required @input="onChangeUsername"/>
<p class="profile-page-url-preview" v-if="shouldShowProfileUrl">{{ `${url}/@${username}` }}</p> <p class="profile-page-url-preview" v-if="shouldShowProfileUrl">{{ `${url}/@${username}` }}</p>
<p class="info" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%%i18n:common.tags.mk-signup.checking%</p> <p class="info" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%%i18n:@checking%</p>
<p class="info" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.available%</p> <p class="info" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw%%i18n:@available%</p>
<p class="info" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.unavailable%</p> <p class="info" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@unavailable%</p>
<p class="info" v-if="usernameState == 'error'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.error%</p> <p class="info" v-if="usernameState == 'error'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@error%</p>
<p class="info" v-if="usernameState == 'invalid-format'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.invalid-format%</p> <p class="info" v-if="usernameState == 'invalid-format'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@invalid-format%</p>
<p class="info" v-if="usernameState == 'min-range'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.too-short%</p> <p class="info" v-if="usernameState == 'min-range'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@too-short%</p>
<p class="info" v-if="usernameState == 'max-range'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.too-long%</p> <p class="info" v-if="usernameState == 'max-range'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@too-long%</p>
</label> </label>
<label class="password"> <label class="password">
<p class="caption">%fa:lock%%i18n:common.tags.mk-signup.password%</p> <p class="caption">%fa:lock%%i18n:@password%</p>
<input v-model="password" type="password" placeholder="%i18n:common.tags.mk-signup.password-placeholder%" autocomplete="off" required @input="onChangePassword"/> <input v-model="password" type="password" placeholder="%i18n:@password-placeholder%" autocomplete="off" required @input="onChangePassword"/>
<div class="meter" v-show="passwordStrength != ''" :data-strength="passwordStrength"> <div class="meter" v-show="passwordStrength != ''" :data-strength="passwordStrength">
<div class="value" ref="passwordMetar"></div> <div class="value" ref="passwordMetar"></div>
</div> </div>
<p class="info" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.weak-password%</p> <p class="info" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@weak-password%</p>
<p class="info" v-if="passwordStrength == 'medium'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.normal-password%</p> <p class="info" v-if="passwordStrength == 'medium'" style="color:#3CB7B5">%fa:check .fw%%i18n:@normal-password%</p>
<p class="info" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.strong-password%</p> <p class="info" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw%%i18n:@strong-password%</p>
</label> </label>
<label class="retype-password"> <label class="retype-password">
<p class="caption">%fa:lock%%i18n:common.tags.mk-signup.password%(%i18n:common.tags.mk-signup.retype%)</p> <p class="caption">%fa:lock%%i18n:@password%(%i18n:@retype%)</p>
<input v-model="retypedPassword" type="password" placeholder="%i18n:common.tags.mk-signup.retype-placeholder%" autocomplete="off" required @input="onChangePasswordRetype"/> <input v-model="retypedPassword" type="password" placeholder="%i18n:@retype-placeholder%" autocomplete="off" required @input="onChangePasswordRetype"/>
<p class="info" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.password-matched%</p> <p class="info" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw%%i18n:@password-matched%</p>
<p class="info" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.password-not-matched%</p> <p class="info" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@password-not-matched%</p>
</label> </label>
<label class="recaptcha"> <label class="recaptcha">
<p class="caption"><template v-if="recaptchaed">%fa:toggle-on%</template><template v-if="!recaptchaed">%fa:toggle-off%</template>%i18n:common.tags.mk-signup.recaptcha%</p> <p class="caption"><template v-if="recaptchaed">%fa:toggle-on%</template><template v-if="!recaptchaed">%fa:toggle-off%</template>%i18n:@recaptcha%</p>
<div class="g-recaptcha" data-callback="onRecaptchaed" data-expired-callback="onRecaptchaExpired" :data-sitekey="recaptchaSitekey"></div> <div class="g-recaptcha" data-callback="onRecaptchaed" data-expired-callback="onRecaptchaExpired" :data-sitekey="recaptchaSitekey"></div>
</label> </label>
<label class="agree-tou"> <label class="agree-tou">
<input name="agree-tou" type="checkbox" autocomplete="off" required/> <input name="agree-tou" type="checkbox" autocomplete="off" required/>
<p><a :href="touUrl" target="_blank">利用規約</a>に同意する</p> <p><a :href="touUrl" target="_blank">利用規約</a>に同意する</p>
</label> </label>
<button type="submit">%i18n:common.tags.mk-signup.create%</button> <button type="submit">%i18n:@create%</button>
</form> </form>
</template> </template>
@ -127,7 +127,7 @@ export default Vue.extend({
location.href = '/'; location.href = '/';
}); });
}).catch(() => { }).catch(() => {
alert('%i18n:common.tags.mk-signup.some-error%'); alert('%i18n:@some-error%');
(window as any).grecaptcha.reset(); (window as any).grecaptcha.reset();
this.recaptchaed = false; this.recaptchaed = false;

View file

@ -1,7 +1,7 @@
<template> <template>
<div class="mk-special-message"> <div class="mk-special-message">
<p v-if="m == 1 && d == 1">%i18n:common.tags.mk-special-message.new-year%</p> <p v-if="m == 1 && d == 1">%i18n:@new-year%</p>
<p v-if="m == 12 && d == 25">%i18n:common.tags.mk-special-message.christmas%</p> <p v-if="m == 12 && d == 25">%i18n:@christmas%</p>
</div> </div>
</template> </template>

View file

@ -2,15 +2,15 @@
<div class="mk-stream-indicator"> <div class="mk-stream-indicator">
<p v-if=" stream.state == 'initializing' "> <p v-if=" stream.state == 'initializing' ">
%fa:spinner .pulse% %fa:spinner .pulse%
<span>%i18n:common.tags.mk-stream-indicator.connecting%<mk-ellipsis/></span> <span>%i18n:@connecting%<mk-ellipsis/></span>
</p> </p>
<p v-if=" stream.state == 'reconnecting' "> <p v-if=" stream.state == 'reconnecting' ">
%fa:spinner .pulse% %fa:spinner .pulse%
<span>%i18n:common.tags.mk-stream-indicator.reconnecting%<mk-ellipsis/></span> <span>%i18n:@reconnecting%<mk-ellipsis/></span>
</p> </p>
<p v-if=" stream.state == 'connected' "> <p v-if=" stream.state == 'connected' ">
%fa:check% %fa:check%
<span>%i18n:common.tags.mk-stream-indicator.connected%</span> <span>%i18n:@connected%</span>
</p> </p>
</div> </div>
</template> </template>

View file

@ -1,11 +1,11 @@
<template> <template>
<div class="mk-twitter-setting"> <div class="mk-twitter-setting">
<p>%i18n:common.tags.mk-twitter-setting.description%<a :href="`${docsUrl}/link-to-twitter`" target="_blank">%i18n:common.tags.mk-twitter-setting.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:common.tags.mk-twitter-setting.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:common.tags.mk-twitter-setting.reconnect%' : '%i18n:common.tags.mk-twitter-setting.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:common.tags.mk-twitter-setting.disconnect%</a> <a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="os.i.twitter" @click.prevent="disconnect">%i18n:@disconnect%</a>
</p> </p>
<p class="id" v-if="os.i.twitter">Twitter ID: {{ os.i.twitter.userId }}</p> <p class="id" v-if="os.i.twitter">Twitter ID: {{ os.i.twitter.userId }}</p>
</div> </div>

View file

@ -5,7 +5,7 @@
<div class="img" :style="{ backgroundImage: `url(${ ctx.img })` }"></div> <div class="img" :style="{ backgroundImage: `url(${ ctx.img })` }"></div>
<p class="name">%fa:spinner .pulse%{{ ctx.name }}</p> <p class="name">%fa:spinner .pulse%{{ ctx.name }}</p>
<p class="status"> <p class="status">
<span class="initing" v-if="ctx.progress == undefined">%i18n:common.tags.mk-uploader.waiting%<mk-ellipsis/></span> <span class="initing" v-if="ctx.progress == undefined">%i18n:@waiting%<mk-ellipsis/></span>
<span class="kb" v-if="ctx.progress != undefined">{{ String(Math.floor(ctx.progress.value / 1024)).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') }}<i>KB</i> / {{ String(Math.floor(ctx.progress.max / 1024)).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') }}<i>KB</i></span> <span class="kb" v-if="ctx.progress != undefined">{{ String(Math.floor(ctx.progress.value / 1024)).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') }}<i>KB</i> / {{ String(Math.floor(ctx.progress.max / 1024)).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') }}<i>KB</i></span>
<span class="percentage" v-if="ctx.progress != undefined">{{ Math.floor((ctx.progress.value / ctx.progress.max) * 100) }}</span> <span class="percentage" v-if="ctx.progress != undefined">{{ Math.floor((ctx.progress.value / ctx.progress.max) * 100) }}</span>
</p> </p>

View file

@ -1,7 +1,7 @@
<template> <template>
<div class="mkw-access-log"> <div class="mkw-access-log">
<mk-widget-container :show-header="props.design == 0"> <mk-widget-container :show-header="props.design == 0">
<template slot="header">%fa:server%%i18n:desktop.tags.mk-access-log-home-widget.title%</template> <template slot="header">%fa:server%%i18n:@title%</template>
<div :class="$style.logs" ref="log"> <div :class="$style.logs" ref="log">
<p v-for="req in requests"> <p v-for="req in requests">

View file

@ -13,13 +13,13 @@
<path class="wave d" d="M29.18,1.06c-0.479-0.502-1.273-0.522-1.775-0.044c-0.016,0.015-0.029,0.029-0.045,0.044c-0.5,0.52-0.5,1.36,0,1.88 c1.361,1.4,2.041,3.24,2.041,5.08s-0.68,3.66-2.041,5.08c-0.5,0.52-0.5,1.36,0,1.88c0.509,0.508,1.332,0.508,1.841,0 c1.86-1.92,2.8-4.44,2.8-6.96C31.99,5.424,30.98,2.931,29.18,1.06z"></path> <path class="wave d" d="M29.18,1.06c-0.479-0.502-1.273-0.522-1.775-0.044c-0.016,0.015-0.029,0.029-0.045,0.044c-0.5,0.52-0.5,1.36,0,1.88 c1.361,1.4,2.041,3.24,2.041,5.08s-0.68,3.66-2.041,5.08c-0.5,0.52-0.5,1.36,0,1.88c0.509,0.508,1.332,0.508,1.841,0 c1.86-1.92,2.8-4.44,2.8-6.96C31.99,5.424,30.98,2.931,29.18,1.06z"></path>
</svg> </svg>
</div> </div>
<p class="fetching" v-if="fetching">%i18n:desktop.tags.mk-broadcast-home-widget.fetching%<mk-ellipsis/></p> <p class="fetching" v-if="fetching">%i18n:@fetching%<mk-ellipsis/></p>
<h1 v-if="!fetching">{{ broadcasts.length == 0 ? '%i18n:desktop.tags.mk-broadcast-home-widget.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:desktop.tags.mk-broadcast-home-widget.have-a-nice-day%</template> <template v-if="broadcasts.length == 0">%i18n:@have-a-nice-day%</template>
</p> </p>
<a v-if="broadcasts.length > 1" @click="next">%i18n:desktop.tags.mk-broadcast-home-widget.next% &gt;&gt;</a> <a v-if="broadcasts.length > 1" @click="next">%i18n:@next% &gt;&gt;</a>
</div> </div>
</template> </template>

View file

@ -1,11 +1,11 @@
<template> <template>
<div class="mkw-donation" :data-mobile="isMobile"> <div class="mkw-donation" :data-mobile="isMobile">
<article> <article>
<h1>%fa:heart%%i18n:desktop.tags.mk-donation-home-widget.title%</h1> <h1>%fa:heart%%i18n:@title%</h1>
<p> <p>
{{ '%i18n:desktop.tags.mk-donation-home-widget.text%'.substr(0, '%i18n:desktop.tags.mk-donation-home-widget.text%'.indexOf('{')) }} {{ '%i18n:@text%'.substr(0, '%i18n:@text%'.indexOf('{')) }}
<a href="https://syuilo.com">@syuilo</a> <a href="https://syuilo.com">@syuilo</a>
{{ '%i18n:desktop.tags.mk-donation-home-widget.text%'.substr('%i18n:desktop.tags.mk-donation-home-widget.text%'.indexOf('}') + 1) }} {{ '%i18n:@text%'.substr('%i18n:@text%'.indexOf('}') + 1) }}
</p> </p>
</article> </article>
</div> </div>

View file

@ -1,13 +1,13 @@
<template> <template>
<div class="mkw-photo-stream" :class="$style.root" :data-melt="props.design == 2"> <div class="mkw-photo-stream" :class="$style.root" :data-melt="props.design == 2">
<mk-widget-container :show-header="props.design == 0" :naked="props.design == 2"> <mk-widget-container :show-header="props.design == 0" :naked="props.design == 2">
<template slot="header">%fa:camera%%i18n:desktop.tags.mk-photo-stream-home-widget.title%</template> <template slot="header">%fa:camera%%i18n:@title%</template>
<p :class="$style.fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p> <p :class="$style.fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<div :class="$style.stream" v-if="!fetching && images.length > 0"> <div :class="$style.stream" v-if="!fetching && images.length > 0">
<div v-for="image in images" :class="$style.img" :style="`background-image: url(${image.url}?thumbnail&size=256)`"></div> <div v-for="image in images" :class="$style.img" :style="`background-image: url(${image.url}?thumbnail&size=256)`"></div>
</div> </div>
<p :class="$style.empty" v-if="!fetching && images.length == 0">%i18n:desktop.tags.mk-photo-stream-home-widget.no-photos%</p> <p :class="$style.empty" v-if="!fetching && images.length == 0">%i18n:@no-photos%</p>
</mk-widget-container> </mk-widget-container>
</div> </div>
</template> </template>

View file

@ -1,8 +1,8 @@
<template> <template>
<div class="mkw-server"> <div class="mkw-server">
<mk-widget-container :show-header="props.design == 0" :naked="props.design == 2"> <mk-widget-container :show-header="props.design == 0" :naked="props.design == 2">
<template slot="header">%fa:server%%i18n:desktop.tags.mk-server-home-widget.title%</template> <template slot="header">%fa:server%%i18n:@title%</template>
<button slot="func" @click="toggle" title="%i18n:desktop.tags.mk-server-home-widget.toggle%">%fa:sort%</button> <button slot="func" @click="toggle" title="%i18n:@toggle%">%fa:sort%</button>
<p :class="$style.fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p> <p :class="$style.fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<template v-if="!fetching"> <template v-if="!fetching">

View file

@ -1,8 +1,8 @@
<template> <template>
<div class="mk-activity" :data-melt="design == 2"> <div class="mk-activity" :data-melt="design == 2">
<template v-if="design == 0"> <template v-if="design == 0">
<p class="title">%fa:chart-bar%%i18n:desktop.tags.mk-activity-widget.title%</p> <p class="title">%fa:chart-bar%%i18n:@title%</p>
<button @click="toggle" title="%i18n:desktop.tags.mk-activity-widget.toggle%">%fa:sort%</button> <button @click="toggle" title="%i18n:@toggle%">%fa:sort%</button>
</template> </template>
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p> <p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<template v-else> <template v-else>

View file

@ -1,9 +1,9 @@
<template> <template>
<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:desktop.tags.mk-calendar-widget.prev%">%fa:chevron-circle-left%</button> <button @click="prev" title="%i18n:@prev%">%fa:chevron-circle-left%</button>
<p class="title">{{ '%i18n:desktop.tags.mk-calendar-widget.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:desktop.tags.mk-calendar-widget.next%">%fa:chevron-circle-right%</button> <button @click="next" title="%i18n:@next%">%fa:chevron-circle-right%</button>
</template> </template>
<div class="calendar"> <div class="calendar">
@ -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:desktop.tags.mk-calendar-widget.go%'" :title="isOutOfRange(i + 1) ? null : '%i18n:@go%'"
> >
<div>{{ i + 1 }}</div> <div>{{ i + 1 }}</div>
</div> </div>

View file

@ -1,8 +1,8 @@
<template> <template>
<mk-window ref="window" @closed="$destroy" width="800px" height="500px" :popout-url="popout"> <mk-window ref="window" @closed="$destroy" width="800px" height="500px" :popout-url="popout">
<template slot="header"> <template slot="header">
<p v-if="usage" :class="$style.info"><b>{{ usage.toFixed(1) }}%</b> %i18n:desktop.tags.mk-drive-browser-window.used%</p> <p v-if="usage" :class="$style.info"><b>{{ usage.toFixed(1) }}%</b> %i18n:@used%</p>
<span :class="$style.title">%fa:cloud%%i18n:desktop.tags.mk-drive-browser-window.drive%</span> <span :class="$style.title">%fa:cloud%%i18n:@drive%</span>
</template> </template>
<mk-drive :class="$style.browser" multiple :init-folder="folder" ref="browser"/> <mk-drive :class="$style.browser" multiple :init-folder="folder" ref="browser"/>
</mk-window> </mk-window>

View file

@ -10,10 +10,10 @@
:title="title" :title="title"
> >
<div class="label" v-if="os.i.avatarId == file.id"><img src="/assets/label.svg"/> <div class="label" v-if="os.i.avatarId == file.id"><img src="/assets/label.svg"/>
<p>%i18n:desktop.tags.mk-drive-browser-file.avatar%</p> <p>%i18n:@avatar%</p>
</div> </div>
<div class="label" v-if="os.i.bannerId == file.id"><img src="/assets/label.svg"/> <div class="label" v-if="os.i.bannerId == file.id"><img src="/assets/label.svg"/>
<p>%i18n:desktop.tags.mk-drive-browser-file.banner%</p> <p>%i18n:@banner%</p>
</div> </div>
<div class="thumbnail" ref="thumbnail" :style="`background-color: ${ background }`"> <div class="thumbnail" ref="thumbnail" :style="`background-color: ${ background }`">
<img :src="`${file.url}?thumbnail&size=128`" alt="" @load="onThumbnailLoaded"/> <img :src="`${file.url}?thumbnail&size=128`" alt="" @load="onThumbnailLoaded"/>
@ -64,18 +64,18 @@ export default Vue.extend({
this.isContextmenuShowing = true; this.isContextmenuShowing = true;
contextmenu(e, [{ contextmenu(e, [{
type: 'item', type: 'item',
text: '%i18n:desktop.tags.mk-drive-browser-file-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:desktop.tags.mk-drive-browser-file-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:desktop.tags.mk-drive-browser-file-contextmenu.download%', text: '%i18n:@contextmenu.download%',
icon: '%fa:download%', icon: '%fa:download%',
}, { }, {
type: 'divider', type: 'divider',
@ -88,22 +88,22 @@ export default Vue.extend({
type: 'divider', type: 'divider',
}, { }, {
type: 'nest', type: 'nest',
text: '%i18n:desktop.tags.mk-drive-browser-file-contextmenu.else-files%', text: '%i18n:@contextmenu.else-files%',
menu: [{ menu: [{
type: 'item', type: 'item',
text: '%i18n:desktop.tags.mk-drive-browser-file-contextmenu.set-as-avatar%', text: '%i18n:@contextmenu.set-as-avatar%',
onClick: this.setAsAvatar onClick: this.setAsAvatar
}, { }, {
type: 'item', type: 'item',
text: '%i18n:desktop.tags.mk-drive-browser-file-contextmenu.set-as-banner%', text: '%i18n:@contextmenu.set-as-banner%',
onClick: this.setAsBanner onClick: this.setAsBanner
}] }]
}, { }, {
type: 'nest', type: 'nest',
text: '%i18n:desktop.tags.mk-drive-browser-file-contextmenu.open-in-app%', text: '%i18n:@contextmenu.open-in-app%',
menu: [{ menu: [{
type: 'item', type: 'item',
text: '%i18n:desktop.tags.mk-drive-browser-file-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:desktop.tags.mk-drive-browser-file-contextmenu.rename-file%', title: '%i18n:@contextmenu.rename-file%',
placeholder: '%i18n:desktop.tags.mk-drive-browser-file-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 => {
@ -156,8 +156,8 @@ export default Vue.extend({
copyUrl() { copyUrl() {
copyToClipboard(this.file.url); copyToClipboard(this.file.url);
(this as any).apis.dialog({ (this as any).apis.dialog({
title: '%fa:check%%i18n:desktop.tags.mk-drive-browser-file-contextmenu.copied%', title: '%fa:check%%i18n:@contextmenu.copied%',
text: '%i18n:desktop.tags.mk-drive-browser-file-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,19 +54,19 @@ export default Vue.extend({
this.isContextmenuShowing = true; this.isContextmenuShowing = true;
contextmenu(e, [{ contextmenu(e, [{
type: 'item', type: 'item',
text: '%i18n:desktop.tags.mk-drive-browser-folder-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:desktop.tags.mk-drive-browser-folder-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:desktop.tags.mk-drive-browser-folder-contextmenu.rename%', text: '%i18n:@contextmenu.rename%',
icon: '%fa:i-cursor%', icon: '%fa:i-cursor%',
onClick: this.rename onClick: this.rename
}, { }, {
@ -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:desktop.tags.mk-drive-browser-folder.unable-to-process%', title: '%fa:exclamation-triangle%%i18n:@unable-to-process%',
text: '%i18n:desktop.tags.mk-drive-browser-folder.circular-reference-detected%', text: '%i18n:@circular-reference-detected%',
actions: [{ actions: [{
text: '%i18n:common.ok%' text: '%i18n:common.ok%'
}] }]
}); });
break; break;
default: default:
alert('%i18n:desktop.tags.mk-drive-browser-folder.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:desktop.tags.mk-drive-browser-folder-contextmenu.rename-folder%', title: '%i18n:@contextmenu.rename-folder%',
placeholder: '%i18n:desktop.tags.mk-drive-browser-folder-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:desktop.tags.mk-drive-browser-nav-folder.drive%' : folder.name }}</span> <span>{{ folder == null ? '%i18n:@drive%' : folder.name }}</span>
</div> </div>
</template> </template>
@ -110,4 +110,7 @@ export default Vue.extend({
&[data-draghover] &[data-draghover]
background #eee background #eee
[data-fa].cloud
margin-right 4px
</style> </style>

View file

@ -10,7 +10,7 @@
<span class="separator" v-if="folder != null">%fa:angle-right%</span> <span class="separator" v-if="folder != null">%fa:angle-right%</span>
<span class="folder current" v-if="folder != null">{{ folder.name }}</span> <span class="folder current" v-if="folder != null">{{ folder.name }}</span>
</div> </div>
<input class="search" type="search" placeholder="&#xf002; %i18n:desktop.tags.mk-drive-browser.search%"/> <input class="search" type="search" placeholder="&#xf002; %i18n:@search%"/>
</nav> </nav>
<div class="main" :class="{ uploading: uploadings.length > 0, fetching }" <div class="main" :class="{ uploading: uploadings.length > 0, fetching }"
ref="main" ref="main"
@ -27,18 +27,18 @@
<x-folder v-for="folder in folders" :key="folder.id" class="folder" :folder="folder"/> <x-folder v-for="folder in folders" :key="folder.id" class="folder" :folder="folder"/>
<!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid --> <!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid -->
<div class="padding" v-for="n in 16"></div> <div class="padding" v-for="n in 16"></div>
<button v-if="moreFolders">%i18n:desktop.tags.mk-drive-browser.load-more%</button> <button v-if="moreFolders">%i18n:@load-more%</button>
</div> </div>
<div class="files" ref="filesContainer" v-if="files.length > 0"> <div class="files" ref="filesContainer" v-if="files.length > 0">
<x-file v-for="file in files" :key="file.id" class="file" :file="file"/> <x-file v-for="file in files" :key="file.id" class="file" :file="file"/>
<!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid --> <!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid -->
<div class="padding" v-for="n in 16"></div> <div class="padding" v-for="n in 16"></div>
<button v-if="moreFiles" @click="fetchMoreFiles">%i18n:desktop.tags.mk-drive-browser.load-more%</button> <button v-if="moreFiles" @click="fetchMoreFiles">%i18n:@load-more%</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">
<p v-if="draghover">%i18n:desktop.tags.mk-drive-browser.empty-draghover%</p> <p v-if="draghover">%i18n:@empty-draghover%</p>
<p v-if="!draghover && folder == null"><strong>%i18n:desktop.tags.mk-drive-browser.empty-drive%</strong><br/>%i18n:desktop.tags.mk-drive-browser.empty-drive-description%</p> <p v-if="!draghover && folder == null"><strong>%i18n:@empty-drive%</strong><br/>%i18n:@empty-drive-description%</p>
<p v-if="!draghover && folder != null">%i18n:desktop.tags.mk-drive-browser.empty-folder%</p> <p v-if="!draghover && folder != null">%i18n:@empty-folder%</p>
</div> </div>
</div> </div>
<div class="fetching" v-if="fetching"> <div class="fetching" v-if="fetching">
@ -138,17 +138,17 @@ export default Vue.extend({
onContextmenu(e) { onContextmenu(e) {
contextmenu(e, [{ contextmenu(e, [{
type: 'item', type: 'item',
text: '%i18n:desktop.tags.mk-drive-browser-base-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:desktop.tags.mk-drive-browser-base-contextmenu.upload%', text: '%i18n:@contextmenu.upload%',
icon: '%fa:upload%', icon: '%fa:upload%',
onClick: this.selectLocalFile onClick: this.selectLocalFile
}, { }, {
type: 'item', type: 'item',
text: '%i18n:desktop.tags.mk-drive-browser-base-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:desktop.tags.mk-drive-browser.unable-to-process%', title: '%fa:exclamation-triangle%%i18n:@unable-to-process%',
text: '%i18n:desktop.tags.mk-drive-browser.circular-reference-detected%', text: '%i18n:@circular-reference-detected%',
actions: [{ actions: [{
text: '%i18n:common.ok%' text: '%i18n:common.ok%'
}] }]
}); });
break; break;
default: default:
alert('%i18n:desktop.tags.mk-drive-browser.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:desktop.tags.mk-drive-browser.url-upload%', title: '%i18n:@url-upload%',
placeholder: '%i18n:desktop.tags.mk-drive-browser.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,
@ -336,8 +336,8 @@ export default Vue.extend({
}); });
(this as any).apis.dialog({ (this as any).apis.dialog({
title: '%fa:check%%i18n:desktop.tags.mk-drive-browser.url-upload-requested%', title: '%fa:check%%i18n:@url-upload-requested%',
text: '%i18n:desktop.tags.mk-drive-browser.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:desktop.tags.mk-drive-browser.create-folder%', title: '%i18n:@create-folder%',
placeholder: '%i18n:desktop.tags.mk-drive-browser.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,6 +1,6 @@
<template> <template>
<mk-window ref="window" width="500px" height="560px" @closed="$destroy"> <mk-window ref="window" width="500px" height="560px" @closed="$destroy">
<span slot="header" :class="$style.header">%fa:comments%メッセージ</span> <span slot="header" :class="$style.header">%fa:comments%%i18n:@title%</span>
<mk-messaging :class="$style.content" @navigate="navigate"/> <mk-messaging :class="$style.content" @navigate="navigate"/>
</mk-window> </mk-window>
</template> </template>

View file

@ -9,9 +9,9 @@
<img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=32`" alt="avatar"/> <img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=32`" alt="avatar"/>
</router-link> </router-link>
%fa:retweet% %fa:retweet%
<span>{{ '%i18n:desktop.tags.mk-timeline-note.reposted-by%'.substr(0, '%i18n:desktop.tags.mk-timeline-note.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:desktop.tags.mk-timeline-note.reposted-by%'.substr('%i18n:desktop.tags.mk-timeline-note.reposted-by%'.indexOf('}') + 1) }}</span> <span>{{ '%i18n:@reposted-by%'.substr('%i18n:@reposted-by%'.indexOf('}') + 1) }}</span>
</p> </p>
<mk-time :time="note.createdAt"/> <mk-time :time="note.createdAt"/>
</div> </div>
@ -57,19 +57,19 @@
</div> </div>
<footer> <footer>
<mk-reactions-viewer :note="p" ref="reactionsViewer"/> <mk-reactions-viewer :note="p" ref="reactionsViewer"/>
<button @click="reply" title="%i18n:desktop.tags.mk-timeline-note.reply%"> <button @click="reply" title="%i18n:@reply%">
%fa:reply%<p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p> %fa:reply%<p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p>
</button> </button>
<button @click="renote" title="%i18n:desktop.tags.mk-timeline-note.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:desktop.tags.mk-timeline-note.add-reaction%"> <button :class="{ reacted: p.myReaction != null }" @click="react" ref="reactButton" title="%i18n:@add-reaction%">
%fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p> %fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p>
</button> </button>
<button @click="menu" ref="menuButton"> <button @click="menu" ref="menuButton">
%fa:ellipsis-h% %fa:ellipsis-h%
</button> </button>
<button title="%i18n:desktop.tags.mk-timeline-note.detail"> <button title="%i18n:@detail">
<template v-if="!isDetailOpened">%fa:caret-down%</template> <template v-if="!isDetailOpened">%fa:caret-down%</template>
<template v-if="isDetailOpened">%fa:caret-up%</template> <template v-if="isDetailOpened">%fa:caret-up%</template>
</button> </button>

View file

@ -93,9 +93,9 @@
</template> </template>
</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:desktop.tags.mk-notifications.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">ありません</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>
</div> </div>
</template> </template>

View file

@ -2,10 +2,10 @@
<mk-window ref="window" is-modal @closed="$destroy"> <mk-window ref="window" is-modal @closed="$destroy">
<span slot="header"> <span slot="header">
<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:desktop.tags.mk-post-form-window.note%</span> <span v-if="!reply">%i18n:@note%</span>
<span v-if="reply">%i18n:desktop.tags.mk-post-form-window.reply%</span> <span v-if="reply">%i18n:@reply%</span>
<span :class="$style.count" v-if="media.length != 0">{{ '%i18n:desktop.tags.mk-post-form-window.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:desktop.tags.mk-post-form-window.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

@ -15,7 +15,7 @@
<x-draggable :list="files" :options="{ animation: 150 }"> <x-draggable :list="files" :options="{ animation: 150 }">
<div v-for="file in files" :key="file.id"> <div v-for="file in files" :key="file.id">
<div class="img" :style="{ backgroundImage: `url(${file.url}?thumbnail&size=64)` }" :title="file.name"></div> <div class="img" :style="{ backgroundImage: `url(${file.url}?thumbnail&size=64)` }" :title="file.name"></div>
<img class="remove" @click="detachMedia(file.id)" src="/assets/desktop/remove.png" title="%i18n:desktop.tags.mk-post-form.attach-cancel%" alt=""/> <img class="remove" @click="detachMedia(file.id)" src="/assets/desktop/remove.png" title="%i18n:@attach-cancel%" alt=""/>
</div> </div>
</x-draggable> </x-draggable>
<p class="remain">{{ 4 - files.length }}/4</p> <p class="remain">{{ 4 - files.length }}/4</p>
@ -23,14 +23,14 @@
<mk-poll-editor v-if="poll" ref="poll" @destroyed="poll = false" @updated="saveDraft()"/> <mk-poll-editor v-if="poll" ref="poll" @destroyed="poll = false" @updated="saveDraft()"/>
</div> </div>
<mk-uploader ref="uploader" @uploaded="attachMedia" @change="onChangeUploadings"/> <mk-uploader ref="uploader" @uploaded="attachMedia" @change="onChangeUploadings"/>
<button class="upload" title="%i18n:desktop.tags.mk-post-form.attach-media-from-local%" @click="chooseFile">%fa:upload%</button> <button class="upload" title="%i18n:@attach-media-from-local%" @click="chooseFile">%fa:upload%</button>
<button class="drive" title="%i18n:desktop.tags.mk-post-form.attach-media-from-drive%" @click="chooseFileFromDrive">%fa:cloud%</button> <button class="drive" title="%i18n:@attach-media-from-drive%" @click="chooseFileFromDrive">%fa:cloud%</button>
<button class="kao" title="%i18n:desktop.tags.mk-post-form.insert-a-kao%" @click="kao">%fa:R smile%</button> <button class="kao" title="%i18n:@insert-a-kao%" @click="kao">%fa:R smile%</button>
<button class="poll" title="%i18n:desktop.tags.mk-post-form.create-poll%" @click="poll = true">%fa:chart-pie%</button> <button class="poll" title="%i18n:@create-poll%" @click="poll = true">%fa:chart-pie%</button>
<button class="geo" title="位置情報を添付する" @click="geo ? removeGeo() : setGeo()">%fa:map-marker-alt%</button> <button class="geo" title="位置情報を添付する" @click="geo ? removeGeo() : setGeo()">%fa:map-marker-alt%</button>
<p class="text-count" :class="{ over: text.length > 1000 }">{{ '%i18n:desktop.tags.mk-post-form.text-remain%'.replace('{}', 1000 - text.length) }}</p> <p class="text-count" :class="{ over: text.length > 1000 }">{{ '%i18n:@text-remain%'.replace('{}', 1000 - text.length) }}</p>
<button :class="{ posting }" class="submit" :disabled="!canPost" @click="post"> <button :class="{ posting }" class="submit" :disabled="!canPost" @click="post">
{{ posting ? '%i18n:desktop.tags.mk-post-form.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>
@ -69,17 +69,17 @@ export default Vue.extend({
}, },
placeholder(): string { placeholder(): string {
return this.renote return this.renote
? '%i18n:desktop.tags.mk-post-form.quote-placeholder%' ? '%i18n:@quote-placeholder%'
: this.reply : this.reply
? '%i18n:desktop.tags.mk-post-form.reply-placeholder%' ? '%i18n:@reply-placeholder%'
: '%i18n:desktop.tags.mk-post-form.note-placeholder%'; : '%i18n:@note-placeholder%';
}, },
submitText(): string { submitText(): string {
return this.renote return this.renote
? '%i18n:desktop.tags.mk-post-form.renote%' ? '%i18n:@renote%'
: this.reply : this.reply
? '%i18n:desktop.tags.mk-post-form.reply%' ? '%i18n:@reply%'
: '%i18n:desktop.tags.mk-post-form.note%'; : '%i18n:@note%';
}, },
canPost(): boolean { canPost(): boolean {
return !this.posting && (this.text.length != 0 || this.files.length != 0 || this.poll || this.renote); return !this.posting && (this.text.length != 0 || this.files.length != 0 || this.poll || this.renote);
@ -236,16 +236,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:desktop.tags.mk-post-form.reposted%' ? '%i18n:@reposted%'
: this.reply : this.reply
? '%i18n:desktop.tags.mk-post-form.replied%' ? '%i18n:@replied%'
: '%i18n:desktop.tags.mk-post-form.posted%'); : '%i18n:@posted%');
}).catch(err => { }).catch(err => {
(this as any).apis.notify(this.renote (this as any).apis.notify(this.renote
? '%i18n:desktop.tags.mk-post-form.renote-failed%' ? '%i18n:@renote-failed%'
: this.reply : this.reply
? '%i18n:desktop.tags.mk-post-form.reply-failed%' ? '%i18n:@reply-failed%'
: '%i18n:desktop.tags.mk-post-form.note-failed%'); : '%i18n:@note-failed%');
}).then(() => { }).then(() => {
this.posting = false; this.posting = false;
}); });

View file

@ -1,6 +1,6 @@
<template> <template>
<mk-window ref="window" is-modal @closed="$destroy"> <mk-window ref="window" is-modal @closed="$destroy">
<span slot="header" :class="$style.header">%fa:retweet%%i18n:desktop.tags.mk-renote-form-window.title%</span> <span slot="header" :class="$style.header">%fa:retweet%%i18n:@title%</span>
<mk-renote-form ref="form" :note="note" @posted="onPosted" @canceled="onCanceled"/> <mk-renote-form ref="form" :note="note" @posted="onPosted" @canceled="onCanceled"/>
</mk-window> </mk-window>
</template> </template>

View file

@ -3,9 +3,9 @@
<mk-note-preview :note="note"/> <mk-note-preview :note="note"/>
<template v-if="!quote"> <template v-if="!quote">
<footer> <footer>
<a class="quote" v-if="!quote" @click="onQuote">%i18n:desktop.tags.mk-renote-form.quote%</a> <a class="quote" v-if="!quote" @click="onQuote">%i18n:@quote%</a>
<button class="cancel" @click="cancel">%i18n:desktop.tags.mk-renote-form.cancel%</button> <button class="cancel" @click="cancel">%i18n:@cancel%</button>
<button class="ok" @click="ok" :disabled="wait">{{ wait ? '%i18n:desktop.tags.mk-renote-form.reposting%' : '%i18n:desktop.tags.mk-renote-form.renote%' }}</button> <button class="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:desktop.tags.mk-renote-form.success%'); (this as any).apis.notify('%i18n:@success%');
}).catch(err => { }).catch(err => {
(this as any).apis.notify('%i18n:desktop.tags.mk-renote-form.failure%'); (this as any).apis.notify('%i18n:@failure%');
}).then(() => { }).then(() => {
this.wait = false; this.wait = false;
}); });

View file

@ -1,42 +0,0 @@
<template>
<mk-window ref="window" is-modal @closed="$destroy">
<span slot="header" :class="$style.header">%fa:retweet%%i18n:desktop.tags.mk-renote-form-window.title%</span>
<mk-renote-form ref="form" :note="note" @posted="onPosted" @canceled="onCanceled"/>
</mk-window>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
props: ['note'],
mounted() {
document.addEventListener('keydown', this.onDocumentKeydown);
},
beforeDestroy() {
document.removeEventListener('keydown', this.onDocumentKeydown);
},
methods: {
onDocumentKeydown(e) {
if (e.target.tagName != 'INPUT' && e.target.tagName != 'TEXTAREA') {
if (e.which == 27) { // Esc
(this.$refs.window as any).close();
}
}
},
onPosted() {
(this.$refs.window as any).close();
},
onCanceled() {
(this.$refs.window as any).close();
}
}
});
</script>
<style lang="stylus" module>
.header
> [data-fa]
margin-right 4px
</style>

View file

@ -1,131 +0,0 @@
<template>
<div class="mk-renote-form">
<mk-note-preview :note="note"/>
<template v-if="!quote">
<footer>
<a class="quote" v-if="!quote" @click="onQuote">%i18n:desktop.tags.mk-renote-form.quote%</a>
<button class="cancel" @click="cancel">%i18n:desktop.tags.mk-renote-form.cancel%</button>
<button class="ok" @click="ok" :disabled="wait">{{ wait ? '%i18n:desktop.tags.mk-renote-form.reposting%' : '%i18n:desktop.tags.mk-renote-form.renote%' }}</button>
</footer>
</template>
<template v-if="quote">
<mk-post-form ref="form" :renote="note" @posted="onChildFormPosted"/>
</template>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
props: ['note'],
data() {
return {
wait: false,
quote: false
};
},
methods: {
ok() {
this.wait = true;
(this as any).api('notes/create', {
renoteId: this.note.id
}).then(data => {
this.$emit('posted');
(this as any).apis.notify('%i18n:desktop.tags.mk-renote-form.success%');
}).catch(err => {
(this as any).apis.notify('%i18n:desktop.tags.mk-renote-form.failure%');
}).then(() => {
this.wait = false;
});
},
cancel() {
this.$emit('canceled');
},
onQuote() {
this.quote = true;
this.$nextTick(() => {
(this.$refs.form as any).focus();
});
},
onChildFormPosted() {
this.$emit('posted');
}
}
});
</script>
<style lang="stylus" scoped>
@import '~const.styl'
.mk-renote-form
> .mk-note-preview
margin 16px 22px
> footer
height 72px
background lighten($theme-color, 95%)
> .quote
position absolute
bottom 16px
left 28px
line-height 40px
button
display block
position absolute
bottom 16px
cursor pointer
padding 0
margin 0
width 120px
height 40px
font-size 1em
outline none
border-radius 4px
&:focus
&:after
content ""
pointer-events none
position absolute
top -5px
right -5px
bottom -5px
left -5px
border 2px solid rgba($theme-color, 0.3)
border-radius 8px
> .cancel
right 148px
color #888
background linear-gradient(to bottom, #ffffff 0%, #f5f5f5 100%)
border solid 1px #e2e2e2
&:hover
background linear-gradient(to bottom, #f9f9f9 0%, #ececec 100%)
border-color #dcdcdc
&:active
background #ececec
border-color #dcdcdc
> .ok
right 16px
font-weight bold
color $theme-color-foreground
background linear-gradient(to bottom, lighten($theme-color, 25%) 0%, lighten($theme-color, 10%) 100%)
border solid 1px lighten($theme-color, 15%)
&:hover
background linear-gradient(to bottom, lighten($theme-color, 8%) 0%, darken($theme-color, 8%) 100%)
border-color $theme-color
&:active
background $theme-color
border-color $theme-color
</style>

View file

@ -1,22 +1,22 @@
<template> <template>
<div class="2fa"> <div class="2fa">
<p>%i18n:desktop.tags.mk-2fa-setting.intro%<a href="%i18n:desktop.tags.mk-2fa-setting.url%" target="_blank">%i18n:desktop.tags.mk-2fa-setting.detail%</a></p> <p>%i18n:@intro%<a href="%i18n:@url%" target="_blank">%i18n:@detail%</a></p>
<div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:desktop.tags.mk-2fa-setting.caution%</p></div> <div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:@caution%</p></div>
<p v-if="!data && !os.i.twoFactorEnabled"><button @click="register" class="ui primary">%i18n:desktop.tags.mk-2fa-setting.register%</button></p> <p v-if="!data && !os.i.twoFactorEnabled"><button @click="register" class="ui primary">%i18n:@register%</button></p>
<template v-if="os.i.twoFactorEnabled"> <template v-if="os.i.twoFactorEnabled">
<p>%i18n:desktop.tags.mk-2fa-setting.already-registered%</p> <p>%i18n:@already-registered%</p>
<button @click="unregister" class="ui">%i18n:desktop.tags.mk-2fa-setting.unregister%</button> <button @click="unregister" class="ui">%i18n:@unregister%</button>
</template> </template>
<div v-if="data"> <div v-if="data">
<ol> <ol>
<li>%i18n:desktop.tags.mk-2fa-setting.authenticator% <a href="https://support.google.com/accounts/answer/1066447" target="_blank">%i18n:desktop.tags.mk-2fa-setting.howtoinstall%</a></li> <li>%i18n:@authenticator% <a href="https://support.google.com/accounts/answer/1066447" target="_blank">%i18n:@howtoinstall%</a></li>
<li>%i18n:desktop.tags.mk-2fa-setting.scan%<br><img :src="data.qr"></li> <li>%i18n:@scan%<br><img :src="data.qr"></li>
<li>%i18n:desktop.tags.mk-2fa-setting.done%<br> <li>%i18n:@done%<br>
<input type="number" v-model="token" class="ui"> <input type="number" v-model="token" class="ui">
<button @click="submit" class="ui primary">%i18n:desktop.tags.mk-2fa-setting.submit%</button> <button @click="submit" class="ui primary">%i18n:@submit%</button>
</li> </li>
</ol> </ol>
<div class="ui info"><p>%fa:info-circle%%i18n:desktop.tags.mk-2fa-setting.info%</p></div> <div class="ui info"><p>%fa:info-circle%%i18n:@info%</p></div>
</div> </div>
</div> </div>
</template> </template>
@ -34,7 +34,7 @@ export default Vue.extend({
methods: { methods: {
register() { register() {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:desktop.tags.mk-2fa-setting.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:desktop.tags.mk-2fa-setting.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:desktop.tags.mk-2fa-setting.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:desktop.tags.mk-2fa-setting.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:desktop.tags.mk-2fa-setting.failed%'); (this as any).apis.notify('%i18n:@failed%');
}); });
} }
} }

View file

@ -1,10 +1,10 @@
<template> <template>
<div class="root api"> <div class="root api">
<p>Token: <code>{{ os.i.token }}</code></p> <p>Token: <code>{{ os.i.token }}</code></p>
<p>%i18n:desktop.tags.mk-api-info.intro%</p> <p>%i18n:@intro%</p>
<div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:desktop.tags.mk-api-info.caution%</p></div> <div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:@caution%</p></div>
<p>%i18n:desktop.tags.mk-api-info.regeneration-of-token%</p> <p>%i18n:@regeneration-of-token%</p>
<button class="ui" @click="regenerateToken">%i18n:desktop.tags.mk-api-info.regenerate-token%</button> <button class="ui" @click="regenerateToken">%i18n:@regenerate-token%</button>
</div> </div>
</template> </template>
@ -15,7 +15,7 @@ export default Vue.extend({
methods: { methods: {
regenerateToken() { regenerateToken() {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:desktop.tags.mk-api-info.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

@ -1,7 +1,7 @@
<template> <template>
<div class="root"> <div class="root">
<div class="none ui info" v-if="!fetching && apps.length == 0"> <div class="none ui info" v-if="!fetching && apps.length == 0">
<p>%fa:info-circle%%i18n:common.tags.mk-authorized-apps.no-apps%</p> <p>%fa:info-circle%%i18n:@no-apps%</p>
</div> </div>
<div class="apps" v-if="apps.length != 0"> <div class="apps" v-if="apps.length != 0">
<div v-for="app in apps"> <div v-for="app in apps">

View file

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<div class="none ui info" v-if="!fetching && users.length == 0"> <div class="none ui info" v-if="!fetching && users.length == 0">
<p>%fa:info-circle%%i18n:desktop.tags.mk-mute-setting.no-users%</p> <p>%fa:info-circle%%i18n:@no-users%</p>
</div> </div>
<div class="users" v-if="users.length != 0"> <div class="users" v-if="users.length != 0">
<div v-for="user in users" :key="user.id"> <div v-for="user in users" :key="user.id">

View file

@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<button @click="reset" class="ui primary">%i18n:desktop.tags.mk-password-setting.reset%</button> <button @click="reset" class="ui primary">%i18n:@reset%</button>
</div> </div>
</template> </template>
@ -11,21 +11,21 @@ export default Vue.extend({
methods: { methods: {
reset() { reset() {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:desktop.tags.mk-password-setting.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:desktop.tags.mk-password-setting.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:desktop.tags.mk-password-setting.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:desktop.tags.mk-password-setting.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:desktop.tags.mk-password-setting.changed%'); (this as any).apis.notify('%i18n:@changed%');
}); });
}); });
}); });

View file

@ -1,27 +1,27 @@
<template> <template>
<div class="profile"> <div class="profile">
<label class="avatar ui from group"> <label class="avatar ui from group">
<p>%i18n:desktop.tags.mk-profile-setting.avatar%</p> <p>%i18n:@avatar%</p>
<img class="avatar" :src="`${os.i.avatarUrl}?thumbnail&size=64`" alt="avatar"/> <img class="avatar" :src="`${os.i.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
<button class="ui" @click="updateAvatar">%i18n:desktop.tags.mk-profile-setting.choice-avatar%</button> <button class="ui" @click="updateAvatar">%i18n:@choice-avatar%</button>
</label> </label>
<label class="ui from group"> <label class="ui from group">
<p>%i18n:desktop.tags.mk-profile-setting.name%</p> <p>%i18n:@name%</p>
<input v-model="name" type="text" class="ui"/> <input v-model="name" type="text" class="ui"/>
</label> </label>
<label class="ui from group"> <label class="ui from group">
<p>%i18n:desktop.tags.mk-profile-setting.location%</p> <p>%i18n:@location%</p>
<input v-model="location" type="text" class="ui"/> <input v-model="location" type="text" class="ui"/>
</label> </label>
<label class="ui from group"> <label class="ui from group">
<p>%i18n:desktop.tags.mk-profile-setting.description%</p> <p>%i18n:@description%</p>
<textarea v-model="description" class="ui"></textarea> <textarea v-model="description" class="ui"></textarea>
</label> </label>
<label class="ui from group"> <label class="ui from group">
<p>%i18n:desktop.tags.mk-profile-setting.birthday%</p> <p>%i18n:@birthday%</p>
<el-date-picker v-model="birthday" type="date" value-format="yyyy-MM-dd"/> <el-date-picker v-model="birthday" type="date" value-format="yyyy-MM-dd"/>
</label> </label>
<button class="ui primary" @click="save">%i18n:desktop.tags.mk-profile-setting.save%</button> <button class="ui primary" @click="save">%i18n:@save%</button>
<section> <section>
<h2>その他</h2> <h2>その他</h2>
<mk-switch v-model="os.i.isBot" @change="onChangeIsBot" text="このアカウントはbotです"/> <mk-switch v-model="os.i.isBot" @change="onChangeIsBot" text="このアカウントはbotです"/>

View file

@ -1,20 +1,20 @@
<template> <template>
<div class="mk-settings"> <div class="mk-settings">
<div class="nav"> <div class="nav">
<p :class="{ active: page == 'profile' }" @mousedown="page = 'profile'">%fa:user .fw%%i18n:desktop.tags.mk-settings.profile%</p> <p :class="{ active: page == 'profile' }" @mousedown="page = 'profile'">%fa:user .fw%%i18n:@profile%</p>
<p :class="{ active: page == 'web' }" @mousedown="page = 'web'">%fa:desktop .fw%Web</p> <p :class="{ active: page == 'web' }" @mousedown="page = 'web'">%fa:desktop .fw%Web</p>
<p :class="{ active: page == 'notification' }" @mousedown="page = 'notification'">%fa:R bell .fw%通知</p> <p :class="{ active: page == 'notification' }" @mousedown="page = 'notification'">%fa:R bell .fw%%i18n:@notification%</p>
<p :class="{ active: page == 'drive' }" @mousedown="page = 'drive'">%fa:cloud .fw%%i18n:desktop.tags.mk-settings.drive%</p> <p :class="{ active: page == 'drive' }" @mousedown="page = 'drive'">%fa:cloud .fw%%i18n:@drive%</p>
<p :class="{ active: page == 'mute' }" @mousedown="page = 'mute'">%fa:ban .fw%%i18n:desktop.tags.mk-settings.mute%</p> <p :class="{ active: page == 'mute' }" @mousedown="page = 'mute'">%fa:ban .fw%%i18n:@mute%</p>
<p :class="{ active: page == 'apps' }" @mousedown="page = 'apps'">%fa:puzzle-piece .fw%アプリ</p> <p :class="{ active: page == 'apps' }" @mousedown="page = 'apps'">%fa:puzzle-piece .fw%%i18n:@apps%</p>
<p :class="{ active: page == 'twitter' }" @mousedown="page = 'twitter'">%fa:B twitter .fw%Twitter</p> <p :class="{ active: page == 'twitter' }" @mousedown="page = 'twitter'">%fa:B twitter .fw%Twitter</p>
<p :class="{ active: page == 'security' }" @mousedown="page = 'security'">%fa:unlock-alt .fw%%i18n:desktop.tags.mk-settings.security%</p> <p :class="{ active: page == 'security' }" @mousedown="page = 'security'">%fa:unlock-alt .fw%%i18n:@security%</p>
<p :class="{ active: page == 'api' }" @mousedown="page = 'api'">%fa:key .fw%API</p> <p :class="{ active: page == 'api' }" @mousedown="page = 'api'">%fa:key .fw%API</p>
<p :class="{ active: page == 'other' }" @mousedown="page = 'other'">%fa:cogs .fw%%i18n:desktop.tags.mk-settings.other%</p> <p :class="{ active: page == 'other' }" @mousedown="page = 'other'">%fa:cogs .fw%%i18n:@other%</p>
</div> </div>
<div class="pages"> <div class="pages">
<section class="profile" v-show="page == 'profile'"> <section class="profile" v-show="page == 'profile'">
<h1>%i18n:desktop.tags.mk-settings.profile%</h1> <h1>%i18n:@profile%</h1>
<x-profile/> <x-profile/>
</section> </section>
@ -98,12 +98,12 @@
</section> </section>
<section class="drive" v-show="page == 'drive'"> <section class="drive" v-show="page == 'drive'">
<h1>%i18n:desktop.tags.mk-settings.drive%</h1> <h1>%i18n:@drive%</h1>
<x-drive/> <x-drive/>
</section> </section>
<section class="mute" v-show="page == 'mute'"> <section class="mute" v-show="page == 'mute'">
<h1>%i18n:desktop.tags.mk-settings.mute%</h1> <h1>%i18n:@mute%</h1>
<x-mute/> <x-mute/>
</section> </section>
@ -118,12 +118,12 @@
</section> </section>
<section class="password" v-show="page == 'security'"> <section class="password" v-show="page == 'security'">
<h1>%i18n:desktop.tags.mk-settings.password%</h1> <h1>%i18n:@password%</h1>
<x-password/> <x-password/>
</section> </section>
<section class="2fa" v-show="page == 'security'"> <section class="2fa" v-show="page == 'security'">
<h1>%i18n:desktop.tags.mk-settings.2fa%</h1> <h1>%i18n:@2fa%</h1>
<x-2fa/> <x-2fa/>
</section> </section>
@ -186,7 +186,7 @@
</section> </section>
<section class="other" v-show="page == 'other'"> <section class="other" v-show="page == 'other'">
<h1>%i18n:desktop.tags.mk-settings.license%</h1> <h1>%i18n:@license%</h1>
<div v-html="license"></div> <div v-html="license"></div>
<a :href="licenseUrl" target="_blank">サードパーティ</a> <a :href="licenseUrl" target="_blank">サードパーティ</a>
</section> </section>

View file

@ -8,26 +8,26 @@
<div class="menu" v-if="isOpen"> <div class="menu" v-if="isOpen">
<ul> <ul>
<li> <li>
<router-link :to="`/@${ os.i.username }`">%fa:user%%i18n:desktop.tags.mk-ui-header-account.profile%%fa:angle-right%</router-link> <router-link :to="`/@${ os.i.username }`">%fa:user%%i18n:@profile%%fa:angle-right%</router-link>
</li> </li>
<li @click="drive"> <li @click="drive">
<p>%fa:cloud%%i18n:desktop.tags.mk-ui-header-account.drive%%fa:angle-right%</p> <p>%fa:cloud%%i18n:@drive%%fa:angle-right%</p>
</li> </li>
<li> <li>
<a href="/i/mentions">%fa:at%%i18n:desktop.tags.mk-ui-header-account.mentions%%fa:angle-right%</a> <a href="/i/mentions">%fa:at%%i18n:@mentions%%fa:angle-right%</a>
</li> </li>
</ul> </ul>
<ul> <ul>
<li> <li>
<a href="/i/customize-home">%fa:wrench%カスタマイズ%fa:angle-right%</a> <a href="/i/customize-home">%fa:wrench%%i18n:@customize%%fa:angle-right%</a>
</li> </li>
<li @click="settings"> <li @click="settings">
<p>%fa:cog%%i18n:desktop.tags.mk-ui-header-account.settings%%fa:angle-right%</p> <p>%fa:cog%%i18n:@settings%%fa:angle-right%</p>
</li> </li>
</ul> </ul>
<ul> <ul>
<li @click="signout"> <li @click="signout">
<p>%fa:power-off%%i18n:desktop.tags.mk-ui-header-account.signout%%fa:angle-right%</p> <p>%fa:power-off%%i18n:@signout%%fa:angle-right%</p>
</li> </li>
</ul> </ul>
</div> </div>

View file

@ -5,20 +5,20 @@
<li class="home" :class="{ active: $route.name == 'index' }"> <li class="home" :class="{ active: $route.name == 'index' }">
<router-link to="/"> <router-link to="/">
%fa:home% %fa:home%
<p>%i18n:desktop.tags.mk-ui-header-nav.home%</p> <p>%i18n:@home%</p>
</router-link> </router-link>
</li> </li>
<li class="messaging"> <li class="messaging">
<a @click="messaging"> <a @click="messaging">
%fa:comments% %fa:comments%
<p>%i18n:desktop.tags.mk-ui-header-nav.messaging%</p> <p>%i18n:@messaging%</p>
<template v-if="hasUnreadMessagingMessages">%fa:circle%</template> <template v-if="hasUnreadMessagingMessages">%fa:circle%</template>
</a> </a>
</li> </li>
<li class="game"> <li class="game">
<a @click="game"> <a @click="game">
%fa:gamepad% %fa:gamepad%
<p>ゲーム</p> <p>%i18n:@game%</p>
<template v-if="hasGameInvitations">%fa:circle%</template> <template v-if="hasGameInvitations">%fa:circle%</template>
</a> </a>
</li> </li>

View file

@ -1,6 +1,6 @@
<template> <template>
<div class="notifications"> <div class="notifications">
<button :data-active="isOpen" @click="toggle" title="%i18n:desktop.tags.mk-ui-header-notifications.title%"> <button :data-active="isOpen" @click="toggle" title="%i18n:@title%">
%fa:R bell%<template v-if="hasUnreadNotifications">%fa:circle%</template> %fa:R bell%<template v-if="hasUnreadNotifications">%fa:circle%</template>
</button> </button>
<div class="pop" v-if="isOpen"> <div class="pop" v-if="isOpen">

View file

@ -1,6 +1,6 @@
<template> <template>
<div class="note"> <div class="note">
<button @click="post" title="%i18n:desktop.tags.mk-ui-header-note-button.note%">%fa:pencil-alt%</button> <button @click="post" title="%i18n:@post%">%fa:pencil-alt%</button>
</div> </div>
</template> </template>

View file

@ -1,7 +1,7 @@
<template> <template>
<form class="search" @submit.prevent="onSubmit"> <form class="search" @submit.prevent="onSubmit">
%fa:search% %fa:search%
<input v-model="q" type="search" placeholder="%i18n:desktop.tags.mk-ui-header-search.placeholder%"/> <input v-model="q" type="search" placeholder="%i18n:@placeholder%"/>
<div class="result"></div> <div class="result"></div>
</form> </form>
</template> </template>

View file

@ -1,9 +1,9 @@
<template> <template>
<mk-ui> <mk-ui>
<main v-if="!fetching"> <main v-if="!fetching">
<a v-if="note.next" :href="note.next">%fa:angle-up%%i18n:desktop.tags.mk-note-page.next%</a> <a v-if="note.next" :href="note.next">%fa:angle-up%%i18n:@next%</a>
<mk-note-detail :note="note"/> <mk-note-detail :note="note"/>
<a v-if="note.prev" :href="note.prev">%fa:angle-down%%i18n:desktop.tags.mk-note-page.prev%</a> <a v-if="note.prev" :href="note.prev">%fa:angle-down%%i18n:@prev%</a>
</main> </main>
</mk-ui> </mk-ui>
</template> </template>

View file

@ -6,9 +6,9 @@
@change-selection="onChangeSelection" @change-selection="onChangeSelection"
/> />
<footer> <footer>
<button class="upload" title="%i18n:desktop.tags.mk-selectdrive-page.upload%" @click="upload">%fa:upload%</button> <button class="upload" title="%i18n:@upload%" @click="upload">%fa:upload%</button>
<button class="cancel" @click="close">%i18n:desktop.tags.mk-selectdrive-page.cancel%</button> <button class="cancel" @click="close">%i18n:@cancel%</button>
<button class="ok" @click="ok">%i18n:desktop.tags.mk-selectdrive-page.ok%</button> <button class="ok" @click="ok">%i18n:@ok%</button>
</footer> </footer>
</div> </div>
</template> </template>
@ -29,7 +29,7 @@ export default Vue.extend({
} }
}, },
mounted() { mounted() {
document.title = '%i18n:desktop.tags.mk-selectdrive-page.title%'; document.title = '%i18n:@title%';
}, },
methods: { methods: {
onSelected(file) { onSelected(file) {

View file

@ -1,13 +1,13 @@
<template> <template>
<div class="followers-you-know"> <div class="followers-you-know">
<p class="title">%fa:users%%i18n:desktop.tags.mk-user.followers-you-know.title%</p> <p class="title">%fa:users%%i18n:@title%</p>
<p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:desktop.tags.mk-user.followers-you-know.loading%<mk-ellipsis/></p> <p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:@loading%<mk-ellipsis/></p>
<div v-if="!fetching && users.length > 0"> <div v-if="!fetching && users.length > 0">
<router-link v-for="user in users" :to="user | userPage" :key="user.id"> <router-link v-for="user in users" :to="user | userPage" :key="user.id">
<img :src="`${user.avatarUrl}?thumbnail&size=64`" :alt="user | userName" v-user-preview="user.id"/> <img :src="`${user.avatarUrl}?thumbnail&size=64`" :alt="user | userName" v-user-preview="user.id"/>
</router-link> </router-link>
</div> </div>
<p class="empty" v-if="!fetching && users.length == 0">%i18n:desktop.tags.mk-user.followers-you-know.no-users%</p> <p class="empty" v-if="!fetching && users.length == 0">%i18n:@no-users%</p>
</div> </div>
</template> </template>

View file

@ -1,7 +1,7 @@
<template> <template>
<div class="friends"> <div class="friends">
<p class="title">%fa:users%%i18n:desktop.tags.mk-user.frequently-replied-users.title%</p> <p class="title">%fa:users%%i18n:@title%</p>
<p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:desktop.tags.mk-user.frequently-replied-users.loading%<mk-ellipsis/></p> <p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:@loading%<mk-ellipsis/></p>
<template v-if="!fetching && users.length != 0"> <template v-if="!fetching && users.length != 0">
<div class="user" v-for="friend in users"> <div class="user" v-for="friend in users">
<router-link class="avatar-anchor" :to="friend | userPage"> <router-link class="avatar-anchor" :to="friend | userPage">
@ -14,7 +14,7 @@
<mk-follow-button :user="friend"/> <mk-follow-button :user="friend"/>
</div> </div>
</template> </template>
<p class="empty" v-if="!fetching && users.length == 0">%i18n:desktop.tags.mk-user.frequently-replied-users.no-users%</p> <p class="empty" v-if="!fetching && users.length == 0">%i18n:@no-users%</p>
</div> </div>
</template> </template>

View file

@ -5,7 +5,7 @@
<x-profile :user="user"/> <x-profile :user="user"/>
<x-photos :user="user"/> <x-photos :user="user"/>
<x-followers-you-know v-if="os.isSignedIn && os.i.id != user.id" :user="user"/> <x-followers-you-know v-if="os.isSignedIn && os.i.id != user.id" :user="user"/>
<p v-if="user.host === null">%i18n:desktop.tags.mk-user.last-used-at%: <b><mk-time :time="user.lastUsedAt"/></b></p> <p v-if="user.host === null">%i18n:@last-used-at%: <b><mk-time :time="user.lastUsedAt"/></b></p>
</div> </div>
</div> </div>
<main> <main>

View file

@ -1,13 +1,13 @@
<template> <template>
<div class="photos"> <div class="photos">
<p class="title">%fa:camera%%i18n:desktop.tags.mk-user.photos.title%</p> <p class="title">%fa:camera%%i18n:@title%</p>
<p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:desktop.tags.mk-user.photos.loading%<mk-ellipsis/></p> <p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:@loading%<mk-ellipsis/></p>
<div class="stream" v-if="!fetching && images.length > 0"> <div class="stream" v-if="!fetching && images.length > 0">
<div v-for="image in images" class="img" <div v-for="image in images" class="img"
:style="`background-image: url(${image.url}?thumbnail&size=256)`" :style="`background-image: url(${image.url}?thumbnail&size=256)`"
></div> ></div>
</div> </div>
<p class="empty" v-if="!fetching && images.length == 0">%i18n:desktop.tags.mk-user.photos.no-photos%</p> <p class="empty" v-if="!fetching && images.length == 0">%i18n:@no-photos%</p>
</div> </div>
</template> </template>

View file

@ -2,9 +2,9 @@
<div class="profile"> <div class="profile">
<div class="friend-form" v-if="os.isSignedIn && os.i.id != user.id"> <div class="friend-form" v-if="os.isSignedIn && os.i.id != user.id">
<mk-follow-button :user="user" size="big"/> <mk-follow-button :user="user" size="big"/>
<p class="followed" v-if="user.isFollowed">%i18n:desktop.tags.mk-user.follows-you%</p> <p class="followed" v-if="user.isFollowed">%i18n:@follows-you%</p>
<p v-if="user.isMuted">%i18n:desktop.tags.mk-user.muted% <a @click="unmute">%i18n:desktop.tags.mk-user.unmute%</a></p> <p v-if="user.isMuted">%i18n:@muted% <a @click="unmute">%i18n:@unmute%</a></p>
<p v-if="!user.isMuted"><a @click="mute">%i18n:desktop.tags.mk-user.mute%</a></p> <p v-if="!user.isMuted"><a @click="mute">%i18n:@mute%</a></p>
</div> </div>
<div class="description" v-if="user.description">{{ user.description }}</div> <div class="description" v-if="user.description">{{ user.description }}</div>
<div class="birthday" v-if="user.host === null && user.profile.birthday"> <div class="birthday" v-if="user.host === null && user.profile.birthday">

View file

@ -1,10 +1,10 @@
<template> <template>
<div class="mkw-channel"> <div class="mkw-channel">
<template v-if="!props.compact"> <template v-if="!props.compact">
<p class="title">%fa:tv%{{ channel ? channel.title : '%i18n:desktop.tags.mk-channel-home-widget.title%' }}</p> <p class="title">%fa:tv%{{ channel ? channel.title : '%i18n:@title%' }}</p>
<button @click="settings" title="%i18n:desktop.tags.mk-channel-home-widget.settings%">%fa:cog%</button> <button @click="settings" title="%i18n:@settings%">%fa:cog%</button>
</template> </template>
<p class="get-started" v-if="props.channel == null">%i18n:desktop.tags.mk-channel-home-widget.get-started%</p> <p class="get-started" v-if="props.channel == null">%i18n:@get-started%</p>
<x-channel class="channel" :channel="channel" v-if="channel != null"/> <x-channel class="channel" :channel="channel" v-if="channel != null"/>
</div> </div>
</template> </template>

View file

@ -1,6 +1,6 @@
<template> <template>
<div class="mkw-messaging"> <div class="mkw-messaging">
<p class="title" v-if="props.design == 0">%fa:comments%%i18n:desktop.tags.mk-messaging-home-widget.title%</p> <p class="title" v-if="props.design == 0">%fa:comments%%i18n:@title%</p>
<mk-messaging ref="index" compact @navigate="navigate"/> <mk-messaging ref="index" compact @navigate="navigate"/>
</div> </div>
</template> </template>

View file

@ -1,8 +1,8 @@
<template> <template>
<div class="mkw-notifications"> <div class="mkw-notifications">
<template v-if="!props.compact"> <template v-if="!props.compact">
<p class="title">%fa:R bell%%i18n:desktop.tags.mk-notifications-home-widget.title%</p> <p class="title">%fa:R bell%%i18n:@title%</p>
<button @click="settings" title="%i18n:desktop.tags.mk-notifications-home-widget.settings%">%fa:cog%</button> <button @click="settings" title="%i18n:@settings%">%fa:cog%</button>
</template> </template>
<mk-notifications/> <mk-notifications/>
</div> </div>

View file

@ -1,15 +1,15 @@
<template> <template>
<div class="mkw-polls"> <div class="mkw-polls">
<template v-if="!props.compact"> <template v-if="!props.compact">
<p class="title">%fa:chart-pie%%i18n:desktop.tags.mk-recommended-polls-home-widget.title%</p> <p class="title">%fa:chart-pie%%i18n:@title%</p>
<button @click="fetch" title="%i18n:desktop.tags.mk-recommended-polls-home-widget.refresh%">%fa:sync%</button> <button @click="fetch" title="%i18n:@refresh%">%fa:sync%</button>
</template> </template>
<div class="poll" v-if="!fetching && poll != null"> <div class="poll" v-if="!fetching && poll != null">
<p v-if="poll.text"><router-link to="poll | notePage">{{ poll.text }}</router-link></p> <p v-if="poll.text"><router-link to="poll | notePage">{{ poll.text }}</router-link></p>
<p v-if="!poll.text"><router-link to="poll | notePage">%fa:link%</router-link></p> <p v-if="!poll.text"><router-link to="poll | notePage">%fa:link%</router-link></p>
<mk-poll :note="poll"/> <mk-poll :note="poll"/>
</div> </div>
<p class="empty" v-if="!fetching && poll == null">%i18n:desktop.tags.mk-recommended-polls-home-widget.nothing%</p> <p class="empty" v-if="!fetching && poll == null">%i18n:@nothing%</p>
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p> <p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
</div> </div>
</template> </template>

View file

@ -1,10 +1,10 @@
<template> <template>
<div class="mkw-post-form"> <div class="mkw-post-form">
<template v-if="props.design == 0"> <template v-if="props.design == 0">
<p class="title">%fa:pencil-alt%%i18n:desktop.tags.mk-post-form-home-widget.title%</p> <p class="title">%fa:pencil-alt%%i18n:@title%</p>
</template> </template>
<textarea :disabled="posting" v-model="text" @keydown="onKeydown" placeholder="%i18n:desktop.tags.mk-post-form-home-widget.placeholder%"></textarea> <textarea :disabled="posting" v-model="text" @keydown="onKeydown" placeholder="%i18n:@placeholder%"></textarea>
<button @click="post" :disabled="posting">%i18n:desktop.tags.mk-post-form-home-widget.note%</button> <button @click="post" :disabled="posting">%i18n:@note%</button>
</div> </div>
</template> </template>

View file

@ -1,15 +1,15 @@
<template> <template>
<div class="mkw-trends"> <div class="mkw-trends">
<template v-if="!props.compact"> <template v-if="!props.compact">
<p class="title">%fa:fire%%i18n:desktop.tags.mk-trends-home-widget.title%</p> <p class="title">%fa:fire%%i18n:@title%</p>
<button @click="fetch" title="%i18n:desktop.tags.mk-trends-home-widget.refresh%">%fa:sync%</button> <button @click="fetch" title="%i18n:@refresh%">%fa:sync%</button>
</template> </template>
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p> <p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<div class="note" v-else-if="note != null"> <div class="note" v-else-if="note != null">
<p class="text"><router-link :to="note | notePage">{{ note.text }}</router-link></p> <p class="text"><router-link :to="note | notePage">{{ note.text }}</router-link></p>
<p class="author"><router-link :to="note.user | userPage">@{{ note.user | acct }}</router-link></p> <p class="author"><router-link :to="note.user | userPage">@{{ note.user | acct }}</router-link></p>
</div> </div>
<p class="empty" v-else>%i18n:desktop.tags.mk-trends-home-widget.nothing%</p> <p class="empty" v-else>%i18n:@nothing%</p>
</div> </div>
</template> </template>

View file

@ -1,8 +1,8 @@
<template> <template>
<div class="mkw-users"> <div class="mkw-users">
<template v-if="!props.compact"> <template v-if="!props.compact">
<p class="title">%fa:users%%i18n:desktop.tags.mk-user-recommendation-home-widget.title%</p> <p class="title">%fa:users%%i18n:@title%</p>
<button @click="refresh" title="%i18n:desktop.tags.mk-user-recommendation-home-widget.refresh%">%fa:sync%</button> <button @click="refresh" title="%i18n:@refresh%">%fa:sync%</button>
</template> </template>
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p> <p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<template v-else-if="users.length != 0"> <template v-else-if="users.length != 0">
@ -17,7 +17,7 @@
<mk-follow-button :user="_user"/> <mk-follow-button :user="_user"/>
</div> </div>
</template> </template>
<p class="empty" v-else>%i18n:desktop.tags.mk-user-recommendation-home-widget.no-one%</p> <p class="empty" v-else>%i18n:@no-one%</p>
</div> </div>
</template> </template>

View file

@ -66,7 +66,7 @@ export default Vue.extend({
const err = const err =
!this.nid.match(/^[a-zA-Z0-9_]+$/) ? 'invalid-format' : !this.nid.match(/^[a-zA-Z0-9_]+$/) ? 'invalid-format' :
this.nid.length < 3 ? 'min-range' : this.nid.length < 1 ? 'min-range' :
this.nid.length > 30 ? 'max-range' : this.nid.length > 30 ? 'max-range' :
null; null;
@ -77,7 +77,7 @@ export default Vue.extend({
this.nidState = 'wait'; this.nidState = 'wait';
(this as any).api('app/nameId/available', { (this as any).api('app/name_id/available', {
nameId: this.nid nameId: this.nid
}).then(result => { }).then(result => {
this.nidState = result.available ? 'ok' : 'unavailable'; this.nidState = result.available ? 'ok' : 'unavailable';

View file

@ -2,7 +2,7 @@
<div class="mk-drive-file-chooser"> <div class="mk-drive-file-chooser">
<div class="body"> <div class="body">
<header> <header>
<h1>%i18n:mobile.tags.mk-drive-selector.select-file%<span class="count" v-if="files.length > 0">({{ files.length }})</span></h1> <h1>%i18n:@select-file%<span class="count" v-if="files.length > 0">({{ files.length }})</span></h1>
<button class="close" @click="cancel">%fa:times%</button> <button class="close" @click="cancel">%fa:times%</button>
<button v-if="multiple" class="ok" @click="ok">%fa:check%</button> <button v-if="multiple" class="ok" @click="ok">%fa:check%</button>
</header> </header>

View file

@ -2,7 +2,7 @@
<div class="mk-drive-folder-chooser"> <div class="mk-drive-folder-chooser">
<div class="body"> <div class="body">
<header> <header>
<h1>%i18n:mobile.tags.mk-drive-folder-selector.select-folder%</h1> <h1>%i18n:@select-folder%</h1>
<button class="close" @click="cancel">%fa:times%</button> <button class="close" @click="cancel">%fa:times%</button>
<button class="ok" @click="ok">%fa:check%</button> <button class="ok" @click="ok">%fa:check%</button>
</header> </header>

View file

@ -35,20 +35,20 @@
<div class="menu"> <div class="menu">
<div> <div>
<a :href="`${file.url}?download`" :download="file.name"> <a :href="`${file.url}?download`" :download="file.name">
%fa:download%%i18n:mobile.tags.mk-drive-file-viewer.download% %fa:download%%i18n:@download%
</a> </a>
<button @click="rename"> <button @click="rename">
%fa:pencil-alt%%i18n:mobile.tags.mk-drive-file-viewer.rename% %fa:pencil-alt%%i18n:@rename%
</button> </button>
<button @click="move"> <button @click="move">
%fa:R folder-open%%i18n:mobile.tags.mk-drive-file-viewer.move% %fa:R folder-open%%i18n:@move%
</button> </button>
</div> </div>
</div> </div>
<div class="exif" v-show="exif"> <div class="exif" v-show="exif">
<div> <div>
<p> <p>
%fa:camera%%i18n:mobile.tags.mk-drive-file-viewer.exif% %fa:camera%%i18n:@exif%
</p> </p>
<pre ref="exif" class="json">{{ exif ? JSON.stringify(exif, null, 2) : '' }}</pre> <pre ref="exif" class="json">{{ exif ? JSON.stringify(exif, null, 2) : '' }}</pre>
</div> </div>
@ -56,7 +56,7 @@
<div class="hash"> <div class="hash">
<div> <div>
<p> <p>
%fa:hashtag%%i18n:mobile.tags.mk-drive-file-viewer.hash% %fa:hashtag%%i18n:@hash%
</p> </p>
<code>{{ file.md5 }}</code> <code>{{ file.md5 }}</code>
</div> </div>

View file

@ -1,7 +1,7 @@
<template> <template>
<div class="mk-drive"> <div class="mk-drive">
<nav ref="nav"> <nav ref="nav">
<a @click.prevent="goRoot()" href="/i/drive">%fa:cloud%%i18n:mobile.tags.mk-drive.drive%</a> <a @click.prevent="goRoot()" href="/i/drive">%fa:cloud%%i18n:@drive%</a>
<template v-for="folder in hierarchyFolders"> <template v-for="folder in hierarchyFolders">
<span :key="folder.id + '>'">%fa:angle-right%</span> <span :key="folder.id + '>'">%fa:angle-right%</span>
<a :key="folder.id" @click.prevent="cd(folder)" :href="`/i/drive/folder/${folder.id}`">{{ folder.name }}</a> <a :key="folder.id" @click.prevent="cd(folder)" :href="`/i/drive/folder/${folder.id}`">{{ folder.name }}</a>
@ -18,26 +18,26 @@
<mk-uploader ref="uploader"/> <mk-uploader ref="uploader"/>
<div class="browser" :class="{ fetching }" v-if="file == null"> <div class="browser" :class="{ fetching }" v-if="file == null">
<div class="info" v-if="info"> <div class="info" v-if="info">
<p v-if="folder == null">{{ (info.usage / info.capacity * 100).toFixed(1) }}% %i18n:mobile.tags.mk-drive.used%</p> <p v-if="folder == null">{{ (info.usage / info.capacity * 100).toFixed(1) }}% %i18n:@used%</p>
<p v-if="folder != null && (folder.foldersCount > 0 || folder.filesCount > 0)"> <p v-if="folder != null && (folder.foldersCount > 0 || folder.filesCount > 0)">
<template v-if="folder.foldersCount > 0">{{ folder.foldersCount }} %i18n:mobile.tags.mk-drive.folder-count%</template> <template v-if="folder.foldersCount > 0">{{ folder.foldersCount }} %i18n:@folder-count%</template>
<template v-if="folder.foldersCount > 0 && folder.filesCount > 0">%i18n:mobile.tags.mk-drive.count-separator%</template> <template v-if="folder.foldersCount > 0 && folder.filesCount > 0">%i18n:@count-separator%</template>
<template v-if="folder.filesCount > 0">{{ folder.filesCount }} %i18n:mobile.tags.mk-drive.file-count%</template> <template v-if="folder.filesCount > 0">{{ folder.filesCount }} %i18n:@file-count%</template>
</p> </p>
</div> </div>
<div class="folders" v-if="folders.length > 0"> <div class="folders" v-if="folders.length > 0">
<x-folder v-for="folder in folders" :key="folder.id" :folder="folder"/> <x-folder v-for="folder in folders" :key="folder.id" :folder="folder"/>
<p v-if="moreFolders">%i18n:mobile.tags.mk-drive.load-more%</p> <p v-if="moreFolders">%i18n:@load-more%</p>
</div> </div>
<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:mobile.tags.mk-drive.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">
<p v-if="folder == null">%i18n:mobile.tags.mk-drive.nothing-in-drive%</p> <p v-if="folder == null">%i18n:@nothing-in-drive%</p>
<p v-if="folder != null">%i18n:mobile.tags.mk-drive.folder-is-empty%</p> <p v-if="folder != null">%i18n:@folder-is-empty%</p>
</div> </div>
</div> </div>
<div class="fetching" v-if="fetching && file == null && files.length == 0 && folders.length == 0"> <div class="fetching" v-if="fetching && file == null && files.length == 0 && folders.length == 0">

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:mobile.tags.mk-follow-button.unfollow%' : '%i18n:mobile.tags.mk-follow-button.follow%' }} {{ user.isFollowing ? '%i18n:@unfollow%' : '%i18n:@follow%' }}
</button> </button>
</template> </template>

View file

@ -54,13 +54,13 @@
</router-link> </router-link>
<footer> <footer>
<mk-reactions-viewer :note="p"/> <mk-reactions-viewer :note="p"/>
<button @click="reply" title="%i18n:mobile.tags.mk-note-detail.reply%"> <button @click="reply" title="%i18n:@reply%">
%fa:reply%<p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p> %fa:reply%<p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p>
</button> </button>
<button @click="renote" title="Renote"> <button @click="renote" title="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:mobile.tags.mk-note-detail.reaction%"> <button :class="{ reacted: p.myReaction != null }" @click="react" ref="reactButton" title="%i18n:@reaction%">
%fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p> %fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p>
</button> </button>
<button @click="menu" ref="menuButton"> <button @click="menu" ref="menuButton">

View file

@ -9,9 +9,9 @@
<img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/> <img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
</router-link> </router-link>
%fa:retweet% %fa:retweet%
<span>{{ '%i18n:mobile.tags.mk-timeline-note.reposted-by%'.substr(0, '%i18n:mobile.tags.mk-timeline-note.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:mobile.tags.mk-timeline-note.reposted-by%'.substr('%i18n:mobile.tags.mk-timeline-note.reposted-by%'.indexOf('}') + 1) }}</span> <span>{{ '%i18n:@reposted-by%'.substr('%i18n:@reposted-by%'.indexOf('}') + 1) }}</span>
</p> </p>
<mk-time :time="note.createdAt"/> <mk-time :time="note.createdAt"/>
</div> </div>

View file

@ -11,9 +11,9 @@
</div> </div>
<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:mobile.tags.mk-notifications.more%' }} {{ fetchingMoreNotifications ? '%i18n:common.loading%' : '%i18n:@more%' }}
</button> </button>
<p class="empty" v-if="notifications.length == 0 && !fetching">%i18n:mobile.tags.mk-notifications.empty%</p> <p class="empty" v-if="notifications.length == 0 && !fetching">%i18n:@empty%</p>
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p> <p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
</div> </div>
</template> </template>

View file

@ -5,12 +5,12 @@
<div> <div>
<span class="text-count" :class="{ over: text.length > 1000 }">{{ 1000 - text.length }}</span> <span class="text-count" :class="{ over: text.length > 1000 }">{{ 1000 - text.length }}</span>
<span class="geo" v-if="geo">%fa:map-marker-alt%</span> <span class="geo" v-if="geo">%fa:map-marker-alt%</span>
<button class="submit" :disabled="posting" @click="post">{{ reply ? '返信' : '%i18n:mobile.tags.mk-post-form.submit%' }}</button> <button class="submit" :disabled="posting" @click="post">{{ reply ? '返信' : '%i18n:@submit%' }}</button>
</div> </div>
</header> </header>
<div class="form"> <div class="form">
<mk-note-preview v-if="reply" :note="reply"/> <mk-note-preview v-if="reply" :note="reply"/>
<textarea v-model="text" ref="text" :disabled="posting" :placeholder="reply ? '%i18n:mobile.tags.mk-post-form.reply-placeholder%' : '%i18n:mobile.tags.mk-post-form.note-placeholder%'"></textarea> <textarea v-model="text" ref="text" :disabled="posting" :placeholder="reply ? '%i18n:@reply-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

@ -10,7 +10,7 @@
<mk-media-list :media-list="note.media"/> <mk-media-list :media-list="note.media"/>
</details> </details>
<details v-if="note.poll"> <details v-if="note.poll">
<summary>%i18n:mobile.tags.mk-sub-note-content.poll%</summary> <summary>%i18n:@poll%</summary>
<mk-poll :note="note"/> <mk-poll :note="note"/>
</details> </details>
</div> </div>

View file

@ -7,10 +7,10 @@
</div> </div>
<div class="empty" v-if="!fetching && notes.length == 0"> <div class="empty" v-if="!fetching && notes.length == 0">
%fa:R comments% %fa:R comments%
%i18n:mobile.tags.mk-home-timeline.empty-timeline% %i18n:@empty%
</div> </div>
<button v-if="!fetching && existMore" @click="more" :disabled="moreFetching" slot="tail"> <button v-if="!fetching && existMore" @click="more" :disabled="moreFetching" slot="tail">
<span v-if="!moreFetching">%i18n:mobile.tags.mk-timeline.load-more%</span> <span v-if="!moreFetching">%i18n:@load-more%</span>
<span v-if="moreFetching">%i18n:common.loading%<mk-ellipsis/></span> <span v-if="moreFetching">%i18n:common.loading%<mk-ellipsis/></span>
</button> </button>
</mk-notes> </mk-notes>
@ -26,7 +26,8 @@ export default Vue.extend({
props: { props: {
date: { date: {
type: Date, type: Date,
required: false required: false,
default: null
} }
}, },
data() { data() {

View file

@ -15,22 +15,22 @@
</router-link> </router-link>
<div class="links"> <div class="links">
<ul> <ul>
<li><router-link to="/">%fa:home%%i18n:mobile.tags.mk-ui-nav.home%%fa:angle-right%</router-link></li> <li><router-link to="/">%fa:home%%i18n:@home%%fa:angle-right%</router-link></li>
<li><router-link to="/i/notifications">%fa:R bell%%i18n:mobile.tags.mk-ui-nav.notifications%<template v-if="hasUnreadNotifications">%fa:circle%</template>%fa:angle-right%</router-link></li> <li><router-link to="/i/notifications">%fa:R bell%%i18n:@notifications%<template v-if="hasUnreadNotifications">%fa:circle%</template>%fa:angle-right%</router-link></li>
<li><router-link to="/i/messaging">%fa:R comments%%i18n:mobile.tags.mk-ui-nav.messaging%<template v-if="hasUnreadMessagingMessages">%fa:circle%</template>%fa:angle-right%</router-link></li> <li><router-link to="/i/messaging">%fa:R comments%%i18n:@messaging%<template v-if="hasUnreadMessagingMessages">%fa:circle%</template>%fa:angle-right%</router-link></li>
<li><router-link to="/othello">%fa:gamepad%ゲーム<template v-if="hasGameInvitations">%fa:circle%</template>%fa:angle-right%</router-link></li> <li><router-link to="/othello">%fa:gamepad%ゲーム<template v-if="hasGameInvitations">%fa:circle%</template>%fa:angle-right%</router-link></li>
</ul> </ul>
<ul> <ul>
<li><router-link to="/i/drive">%fa:cloud%%i18n:mobile.tags.mk-ui-nav.drive%%fa:angle-right%</router-link></li> <li><router-link to="/i/drive">%fa:cloud%%i18n:@drive%%fa:angle-right%</router-link></li>
</ul> </ul>
<ul> <ul>
<li><a @click="search">%fa:search%%i18n:mobile.tags.mk-ui-nav.search%%fa:angle-right%</a></li> <li><a @click="search">%fa:search%%i18n:@search%%fa:angle-right%</a></li>
</ul> </ul>
<ul> <ul>
<li><router-link to="/i/settings">%fa:cog%%i18n:mobile.tags.mk-ui-nav.settings%%fa:angle-right%</router-link></li> <li><router-link to="/i/settings">%fa:cog%%i18n:@settings%%fa:angle-right%</router-link></li>
</ul> </ul>
</div> </div>
<a :href="aboutUrl"><p class="about">%i18n:mobile.tags.mk-ui-nav.about%</p></a> <a :href="aboutUrl"><p class="about">%i18n:@about%</p></a>
</div> </div>
</transition> </transition>
</div> </div>
@ -92,7 +92,7 @@ export default Vue.extend({
}, },
methods: { methods: {
search() { search() {
const query = window.prompt('%i18n:mobile.tags.mk-ui-nav.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

@ -6,10 +6,10 @@
</div> </div>
<div class="empty" v-if="!fetching && notes.length == 0"> <div class="empty" v-if="!fetching && notes.length == 0">
%fa:R comments% %fa:R comments%
{{ withMedia ? '%i18n:mobile.tags.mk-user-timeline.no-notes-with-media%' : '%i18n:mobile.tags.mk-user-timeline.no-notes%' }} {{ withMedia ? '%i18n:@no-notes-with-media%' : '%i18n:@no-notes%' }}
</div> </div>
<button v-if="!fetching && existMore" @click="more" :disabled="moreFetching" slot="tail"> <button v-if="!fetching && existMore" @click="more" :disabled="moreFetching" slot="tail">
<span v-if="!moreFetching">%i18n:mobile.tags.mk-user-timeline.load-more%</span> <span v-if="!moreFetching">%i18n:@load-more%</span>
<span v-if="moreFetching">%i18n:common.loading%<mk-ellipsis/></span> <span v-if="moreFetching">%i18n:common.loading%<mk-ellipsis/></span>
</button> </button>
</mk-notes> </mk-notes>

View file

@ -1,14 +1,14 @@
<template> <template>
<div class="mk-users-list"> <div class="mk-users-list">
<nav> <nav>
<span :data-is-active="mode == 'all'" @click="mode = 'all'">%i18n:mobile.tags.mk-users-list.all%<span>{{ count }}</span></span> <span :data-is-active="mode == 'all'" @click="mode = 'all'">%i18n:@all%<span>{{ count }}</span></span>
<span v-if="os.isSignedIn && youKnowCount" :data-is-active="mode == 'iknow'" @click="mode = 'iknow'">%i18n:mobile.tags.mk-users-list.known%<span>{{ youKnowCount }}</span></span> <span v-if="os.isSignedIn && youKnowCount" :data-is-active="mode == 'iknow'" @click="mode = 'iknow'">%i18n:@known%<span>{{ youKnowCount }}</span></span>
</nav> </nav>
<div class="users" v-if="!fetching && users.length != 0"> <div class="users" v-if="!fetching && users.length != 0">
<mk-user-preview v-for="u in users" :user="u" :key="u.id"/> <mk-user-preview v-for="u in users" :user="u" :key="u.id"/>
</div> </div>
<button class="more" v-if="!fetching && next != null" @click="more" :disabled="moreFetching"> <button class="more" v-if="!fetching && next != null" @click="more" :disabled="moreFetching">
<span v-if="!moreFetching">%i18n:mobile.tags.mk-users-list.load-more%</span> <span v-if="!moreFetching">%i18n:@load-more%</span>
<span v-if="moreFetching">%i18n:common.loading%<mk-ellipsis/></span> <span v-if="moreFetching">%i18n:common.loading%<mk-ellipsis/></span>
</button> </button>
<p class="no" v-if="!fetching && users.length == 0"> <p class="no" v-if="!fetching && users.length == 0">

View file

@ -3,7 +3,7 @@
<span slot="header"> <span slot="header">
<template v-if="folder">%fa:R folder-open%{{ folder.name }}</template> <template v-if="folder">%fa:R folder-open%{{ folder.name }}</template>
<template v-if="file"><mk-file-type-icon data-icon :type="file.type"/>{{ file.name }}</template> <template v-if="file"><mk-file-type-icon data-icon :type="file.type"/>{{ file.name }}</template>
<template v-if="!folder && !file">%fa:cloud%%i18n:mobile.tags.mk-drive-page.drive%</template> <template v-if="!folder && !file">%fa:cloud%%i18n:@drive%</template>
</span> </span>
<template slot="func"><button @click="fn">%fa:ellipsis-h%</button></template> <template slot="func"><button @click="fn">%fa:ellipsis-h%</button></template>
<mk-drive <mk-drive

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:mobile.tags.mk-user-followers-page.followers-of%'.replace('{}', name) }} {{ '%i18n:@followers-of%'.replace('{}', name) }}
</template> </template>
<mk-users-list <mk-users-list
v-if="!fetching" v-if="!fetching"
@ -11,7 +11,7 @@
:you-know-count="user.followersYouKnowCount" :you-know-count="user.followersYouKnowCount"
@loaded="onLoaded" @loaded="onLoaded"
> >
%i18n:mobile.tags.mk-user-followers.no-users% %i18n:@no-users%
</mk-users-list> </mk-users-list>
</mk-ui> </mk-ui>
</template> </template>
@ -52,7 +52,7 @@ export default Vue.extend({
this.user = user; this.user = user;
this.fetching = false; this.fetching = false;
document.title = '%i18n:mobile.tags.mk-user-followers-page.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:mobile.tags.mk-user-following-page.following-of%'.replace('{}', name) }} {{ '%i18n:@following-of%'.replace('{}', name) }}
</template> </template>
<mk-users-list <mk-users-list
v-if="!fetching" v-if="!fetching"
@ -11,7 +11,7 @@
:you-know-count="user.followingYouKnowCount" :you-know-count="user.followingYouKnowCount"
@loaded="onLoaded" @loaded="onLoaded"
> >
%i18n:mobile.tags.mk-user-following.no-users% %i18n:@no-users%
</mk-users-list> </mk-users-list>
</mk-ui> </mk-ui>
</template> </template>
@ -51,7 +51,7 @@ export default Vue.extend({
this.user = user; this.user = user;
this.fetching = false; this.fetching = false;
document.title = '%i18n:mobile.tags.mk-user-followers-page.followers-of%'.replace('{}', this.name) + ' | Misskey'; document.title = '%i18n:@followers-of%'.replace('{}', this.name) + ' | Misskey';
}); });
}, },
onLoaded() { onLoaded() {

Some files were not shown because too many files have changed in this diff Show more