From 7dd709f8a63bf55e4f57d216d22b55b7ab3d91d7 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Sun, 26 Mar 2017 03:23:19 +0900
Subject: [PATCH] wip #313

---
 locales/en.json                               | 42 ++++++++++++++++++-
 locales/ja.json                               | 42 ++++++++++++++++++-
 src/web/app/desktop/tags/post-form-window.tag |  8 ++--
 src/web/app/desktop/tags/post-form.tag        | 40 +++++++++---------
 .../app/desktop/tags/ui-header-account.tag    | 21 ++++++----
 src/web/app/desktop/tags/ui-header-nav.tag    |  6 +--
 src/web/app/desktop/tags/ui-header-search.tag |  2 +-
 webpack.config.ts                             | 18 +++++++-
 8 files changed, 141 insertions(+), 38 deletions(-)

diff --git a/locales/en.json b/locales/en.json
index 2153daa00..6d0c96fa8 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -29,7 +29,47 @@
 	"desktop": {
 		"tags": {
 			"mk-ui-header-nav": {
-				"home": "Home"
+				"home": "Home",
+				"messaging": "Messaging",
+				"info": "Info",
+				"live": "Live"
+			},
+			"mk-ui-header-search": {
+				"placeholder": "Search"
+			},
+			"mk-ui-header-account": {
+				"profile": "Your profile",
+				"drive": "Drive",
+				"mentions": "Mentions",
+				"settings": "Settings",
+				"signout": "Sign out"
+			},
+			"mk-post-form": {
+				"post-placeholder": "What's happening?",
+				"reply-placeholder": "この投稿への返信...",
+				"quote-placeholder": "この投稿を引用...",
+				"post": "Post",
+				"reply": "Reply",
+				"repost": "Repost",
+				"posted": "Posted!",
+				"replied": "Replied!",
+				"reposted": "Reposted!",
+				"post-failed": "Failed to post",
+				"reply-failed": "Failed to reply",
+				"repost-failed": "Failed to repost",
+				"posting": "Posting",
+				"attach-media-from-local": "Attach media from your pc",
+				"attach-media-from-drive": "Attach media from the drive",
+				"attach-cancel": "Cancel to attach",
+				"insert-the-cat": "Insert the cat",
+				"create-poll": "Create a poll",
+				"text-remain": "{} characters remaining"
+			},
+			"mk-post-form-window": {
+				"post": "New post",
+				"reply": "Reply",
+				"attaches": "{} media attached",
+				"uploading-media": "{} media uploading"
 			}
 		}
 	}
diff --git a/locales/ja.json b/locales/ja.json
index 4131af960..dbe11f5e8 100644
--- a/locales/ja.json
+++ b/locales/ja.json
@@ -29,7 +29,47 @@
 	"desktop": {
 		"tags": {
 			"mk-ui-header-nav": {
-				"home": "ホーム"
+				"home": "ホーム",
+				"messaging": "メッセージ",
+				"info": "お知らせ",
+				"live": "ライブ"
+			},
+			"mk-ui-header-search": {
+				"placeholder": "検索"
+			},
+			"mk-ui-header-account": {
+				"profile": "プロフィール",
+				"drive": "ドライブ",
+				"mentions": "あなた宛て",
+				"settings": "設定",
+				"signout": "サインアウト"
+			},
+			"mk-post-form": {
+				"post-placeholder": "いまどうしてる?",
+				"reply-placeholder": "この投稿への返信...",
+				"quote-placeholder": "この投稿を引用...",
+				"post": "投稿",
+				"reply": "返信",
+				"repost": "Repost",
+				"posted": "投稿しました!",
+				"replied": "返信しました!",
+				"reposted": "Repostしました!",
+				"post-failed": "投稿できませんでした",
+				"reply-failed": "返信できませんでした",
+				"repost-failed": "Repostできませんでした",
+				"posting": "投稿中",
+				"attach-media-from-local": "PCからメディアを添付",
+				"attach-media-from-drive": "ドライブからメディアを添付",
+				"attach-cancel": "添付取り消し",
+				"insert-the-cat": "猫挿入",
+				"create-poll": "投票を作成",
+				"text-remain": "のこり{}文字"
+			},
+			"mk-post-form-window": {
+				"post": "新規投稿",
+				"reply": "返信",
+				"attaches": "添付: {}メディア",
+				"uploading-media": "{}つのメディアをアップロード中"
 			}
 		}
 	}
diff --git a/src/web/app/desktop/tags/post-form-window.tag b/src/web/app/desktop/tags/post-form-window.tag
index adc70a93f..745aa64c8 100644
--- a/src/web/app/desktop/tags/post-form-window.tag
+++ b/src/web/app/desktop/tags/post-form-window.tag
@@ -1,10 +1,10 @@
 <mk-post-form-window>
 	<mk-window ref="window" is-modal={ true }>
 		<yield to="header">
-			<span if={ !parent.opts.reply }>新規投稿</span>
-			<span if={ parent.opts.reply }>返信</span>
-			<span class="files" if={ parent.files.length != 0 }>添付: { parent.files.length }ファイル</span>
-			<span class="uploading-files" if={ parent.uploadingFiles.length != 0 }>{ parent.uploadingFiles.length }個のファイルをアップロード中<mk-ellipsis></mk-ellipsis></span>
+			<span if={ !parent.opts.reply }>%i18n:desktop.tags.mk-post-form-window.post%</span>
+			<span if={ parent.opts.reply }>%i18n:desktop.tags.mk-post-form-window.reply%</span>
+			<span class="files" if={ parent.files.length != 0 }>{ '%i18n:desktop.tags.mk-post-form-window.attaches%'.replace('{}', parent.files.length) }</span>
+			<span class="uploading-files" if={ parent.uploadingFiles.length != 0 }>{ '%i18n:desktop.tags.mk-post-form-window.uploading-media%'.replace('{}', parent.uploadingFiles.length) }<mk-ellipsis></mk-ellipsis></span>
 		</yield>
 		<yield to="content">
 			<div class="ref" if={ parent.opts.reply }>
diff --git a/src/web/app/desktop/tags/post-form.tag b/src/web/app/desktop/tags/post-form.tag
index 1f6303bcb..ca6b5eb9d 100644
--- a/src/web/app/desktop/tags/post-form.tag
+++ b/src/web/app/desktop/tags/post-form.tag
@@ -5,22 +5,22 @@
 			<ul>
 				<li each={ files }>
 					<div class="img" style="background-image: url({ url + '?thumbnail&size=64' })" title={ name }></div>
-					<img class="remove" onclick={ removeFile } src="/assets/desktop/remove.png" title="添付取り消し" alt=""/>
+					<img class="remove" onclick={ removeFile } src="/assets/desktop/remove.png" title="%i18n:desktop.tags.mk-post-form.attach-cancel%" alt=""/>
 				</li>
-				<li class="add" if={ files.length < 4 } title="PCからファイルを添付" onclick={ selectFile }><i class="fa fa-plus"></i></li>
+				<li class="add" if={ files.length < 4 } title="%i18n:desktop.tags.mk-post-form.attach-media-from-local%" onclick={ selectFile }><i class="fa fa-plus"></i></li>
 			</ul>
 			<p class="remain">{ 4 - files.length }/4</p>
 		</div>
 		<mk-poll-editor if={ poll } ref="poll" ondestroy={ onPollDestroyed }></mk-poll-editor>
 	</div>
 	<mk-uploader ref="uploader"></mk-uploader>
-	<button ref="upload" title="PCからファイルを添付" onclick={ selectFile }><i class="fa fa-upload"></i></button>
-	<button ref="drive" title="ドライブからファイルを添付" onclick={ selectFileFromDrive }><i class="fa fa-cloud"></i></button>
-	<button class="cat" title="Insert The Cat" onclick={ cat }><i class="fa fa-smile-o"></i></button>
-	<button class="poll" title="投票を作成" onclick={ addPoll }><i class="fa fa-pie-chart"></i></button>
-	<p class="text-count { over: refs.text.value.length > 1000 }">のこり{ 1000 - refs.text.value.length }文字</p>
+	<button ref="upload" title="%i18n:desktop.tags.mk-post-form.attach-media-from-local%" onclick={ selectFile }><i class="fa fa-upload"></i></button>
+	<button ref="drive" title="%i18n:desktop.tags.mk-post-form.attach-media-from-drive%" onclick={ selectFileFromDrive }><i class="fa fa-cloud"></i></button>
+	<button class="cat" title="%i18n:desktop.tags.mk-post-form.insert-the-cat%" onclick={ cat }><i class="fa fa-smile-o"></i></button>
+	<button class="poll" title="%i18n:desktop.tags.mk-post-form.create-poll%" onclick={ addPoll }><i class="fa fa-pie-chart"></i></button>
+	<p class="text-count { over: refs.text.value.length > 1000 }">{ '%i18n:desktop.tags.mk-post-form.text-remain%'.replace('{}', 1000 - refs.text.value.length) }</p>
 	<button class={ wait: wait } ref="submit" disabled={ wait || (refs.text.value.length == 0 && files.length == 0 && !poll && !repost) } onclick={ post }>
-		{ wait ? '投稿中' : submitText }<mk-ellipsis if={ wait }></mk-ellipsis>
+		{ wait ? '%i18n:desktop.tags.mk-post-form.posting%' : submitText }<mk-ellipsis if={ wait }></mk-ellipsis>
 	</button>
 	<input ref="file" type="file" accept="image/*" multiple="multiple" tabindex="-1" onchange={ changeFile }/>
 	<div class="dropzone" if={ draghover }></div>
@@ -329,16 +329,16 @@
 		if (this.repost == '') this.repost = null;
 
 		this.placeholder = this.repost
-			? 'この投稿を引用...'
+			? '%i18n:desktop.tags.mk-post-form.quote-placeholder%'
 			: this.inReplyToPost
-				? 'この投稿への返信...'
-				: 'いまどうしてる?';
+				? '%i18n:desktop.tags.mk-post-form.reply-placeholder%'
+				: '%i18n:desktop.tags.mk-post-form.post-placeholder%';
 
 		this.submitText = this.repost
-			? 'Repost'
+			? '%i18n:desktop.tags.mk-post-form.repost%'
 			: this.inReplyToPost
-				? '返信'
-				: '投稿';
+				? '%i18n:desktop.tags.mk-post-form.reply%'
+				: '%i18n:desktop.tags.mk-post-form.post%';
 
 		this.draftId = this.repost
 			? 'repost:' + this.repost.id
@@ -489,16 +489,16 @@
 				this.removeDraft();
 				this.trigger('post');
 				notify(this.repost
-					? 'Repostしました!'
+					? '%i18n:desktop.tags.mk-post-form.reposted%'
 					: this.inReplyToPost
-						? '返信しました!'
-						: '投稿しました!');
+						? '%i18n:desktop.tags.mk-post-form.replied%'
+						: '%i18n:desktop.tags.mk-post-form.posted%');
 			}).catch(err => {
 				notify(this.repost
-					? 'Repostできませんでした'
+					? '%i18n:desktop.tags.mk-post-form.repost-failed%'
 					: this.inReplyToPost
-						? '返信できませんでした'
-						: '投稿できませんでした');
+						? '%i18n:desktop.tags.mk-post-form.reply-failed%'
+						: '%i18n:desktop.tags.mk-post-form.post-failed%');
 			}).then(() => {
 				this.update({
 					wait: false
diff --git a/src/web/app/desktop/tags/ui-header-account.tag b/src/web/app/desktop/tags/ui-header-account.tag
index e47572edb..a8f83ad00 100644
--- a/src/web/app/desktop/tags/ui-header-account.tag
+++ b/src/web/app/desktop/tags/ui-header-account.tag
@@ -1,21 +1,28 @@
 <mk-ui-header-account>
-	<button class="header" data-active={ isOpen.toString() } onclick={ toggle }><span class="username">{ I.username }<i class="fa fa-angle-down" if={ !isOpen }></i><i class="fa fa-angle-up" if={ isOpen }></i></span><img class="avatar" src={ I.avatar_url + '?thumbnail&size=64' } alt="avatar"/></button>
+	<button class="header" data-active={ isOpen.toString() } onclick={ toggle }>
+		<span class="username">{ I.username }<i class="fa fa-angle-down" if={ !isOpen }></i><i class="fa fa-angle-up" if={ isOpen }></i></span>
+		<img class="avatar" src={ I.avatar_url + '?thumbnail&size=64' } alt="avatar"/>
+	</button>
 	<div class="menu" if={ isOpen }>
 		<ul>
-			<li><a href={ '/' + I.username }><i class="fa fa-user"></i>プロフィール<i class="fa fa-angle-right"></i></a></li>
-			<li onclick={ drive }>
-				<p><i class="fa fa-cloud"></i>ドライブ<i class="fa fa-angle-right"></i></p>
+			<li>
+				<a href={ '/' + I.username }><i class="fa fa-user"></i>%i18n:desktop.tags.mk-ui-header-account.profile%<i class="fa fa-angle-right"></i></a>
+			</li>
+			<li onclick={ drive }>
+				<p><i class="fa fa-cloud"></i>%i18n:desktop.tags.mk-ui-header-account.drive%<i class="fa fa-angle-right"></i></p>
+			</li>
+			<li>
+				<a href="/i>mentions"><i class="fa fa-at"></i>%i18n:desktop.tags.mk-ui-header-account.mentions%<i class="fa fa-angle-right"></i></a>
 			</li>
-			<li><a href="/i>mentions"><i class="fa fa-at"></i>あなた宛て<i class="fa fa-angle-right"></i></a></li>
 		</ul>
 		<ul>
 			<li onclick={ settings }>
-				<p><i class="fa fa-cog"></i>設定<i class="fa fa-angle-right"></i></p>
+				<p><i class="fa fa-cog"></i>%i18n:desktop.tags.mk-ui-header-account.settings%<i class="fa fa-angle-right"></i></p>
 			</li>
 		</ul>
 		<ul>
 			<li onclick={ signout }>
-				<p><i class="fa fa-power-off"></i>サインアウト<i class="fa fa-angle-right"></i></p>
+				<p><i class="fa fa-power-off"></i>%i18n:desktop.tags.mk-ui-header-account.signout%<i class="fa fa-angle-right"></i></p>
 			</li>
 		</ul>
 	</div>
diff --git a/src/web/app/desktop/tags/ui-header-nav.tag b/src/web/app/desktop/tags/ui-header-nav.tag
index 2fb0f8c51..80352dc12 100644
--- a/src/web/app/desktop/tags/ui-header-nav.tag
+++ b/src/web/app/desktop/tags/ui-header-nav.tag
@@ -9,20 +9,20 @@
 		<li class="messaging">
 			<a onclick={ messaging }>
 				<i class="fa fa-comments"></i>
-				<p>メッセージ</p>
+				<p>%i18n:desktop.tags.mk-ui-header-nav.messaging%</p>
 				<i class="fa fa-circle" if={ hasUnreadMessagingMessages }></i>
 			</a>
 		</li>
 		<li class="info">
 			<a href="https://twitter.com/misskey_xyz" target="_blank">
 				<i class="fa fa-info"></i>
-				<p>お知らせ</p>
+				<p>%i18n:desktop.tags.mk-ui-header-nav.info%</p>
 			</a>
 		</li>
 		<li class="live">
 			<a href="https://misskey.tk" target="_blank">
 				<i class="fa fa-television"></i>
-				<p>ライブ</p>
+				<p>%i18n:desktop.tags.mk-ui-header-nav.live%</p>
 			</a>
 		</li>
 	</ul>
diff --git a/src/web/app/desktop/tags/ui-header-search.tag b/src/web/app/desktop/tags/ui-header-search.tag
index ff1a313ce..616476f42 100644
--- a/src/web/app/desktop/tags/ui-header-search.tag
+++ b/src/web/app/desktop/tags/ui-header-search.tag
@@ -1,6 +1,6 @@
 <mk-ui-header-search>
 	<form class="search" onsubmit={ onsubmit }>
-		<input ref="q" type="search" placeholder="&#xf002; 検索"/>
+		<input ref="q" type="search" placeholder="&#xf002; %i18n:desktop.tags.mk-ui-header-search.placeholder%"/>
 		<div class="result"></div>
 	</form>
 	<style>
diff --git a/webpack.config.ts b/webpack.config.ts
index b67c0e903..b501eb1ef 100644
--- a/webpack.config.ts
+++ b/webpack.config.ts
@@ -33,7 +33,23 @@ module.exports = (Object as any).entries(languages).map(([lang, locale]) => {
 					exclude: /node_modules/,
 					loader: StringReplacePlugin.replace({
 						replacements: [
-							{ pattern: /%i18n:(.+?)%/g, replacement: (_, text) => eval('locale' + text.split('.').map(x => `['${x}']`).join('')) }
+							{ pattern: /%i18n:(.+?)%/g, replacement: (_, key) => {
+								let text = locale;
+								const error = key.split('.').some(k => {
+									if (text.hasOwnProperty(k)) {
+										text = text[k];
+										return false;
+									} else {
+										return true;
+									}
+								});
+								if (error) {
+									console.warn(`key '${key}' not found in '${lang}'`);
+									return '-UNTRANSLATED-';
+								} else {
+									return text.replace(/'/g, '\\\'').replace(/"/g, '\\"');
+								}
+							} }
 						]
 					})
 				},