diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 0cad52d128..ed8daece6c 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -990,6 +990,12 @@ desktop/views/components/sub-note-content.vue:
   media-count: "{}つのメディア"
   poll: "アンケート"
 
+desktop/views/components/settings.tags.vue:
+  title: "タグ"
+  query: "クエリ (省略可)"
+  add: "追加"
+  save: "保存"
+
 desktop/views/components/taskmanager.vue:
   title: "タスクマネージャ"
 
diff --git a/src/client/app/common/views/components/ui/textarea.vue b/src/client/app/common/views/components/ui/textarea.vue
index 0bdd4aadd0..d265c7ac6d 100644
--- a/src/client/app/common/views/components/ui/textarea.vue
+++ b/src/client/app/common/views/components/ui/textarea.vue
@@ -1,5 +1,5 @@
 <template>
-<div class="ui-textarea" :class="{ focused, filled, tall }">
+<div class="ui-textarea" :class="{ focused, filled, tall, pre }">
 	<div class="input">
 		<span class="label" ref="label"><slot></slot></span>
 		<textarea ref="input"
@@ -46,6 +46,11 @@ export default Vue.extend({
 			required: false,
 			default: false
 		},
+		pre: {
+			type: Boolean,
+			required: false,
+			default: false
+		},
 	},
 	data() {
 		return {
@@ -175,6 +180,11 @@ root(fill)
 			> textarea
 				min-height 200px
 
+	&.pre
+		> .input
+			> textarea
+				white-space pre
+
 .ui-textarea.fill
 	root(true)
 
diff --git a/src/client/app/desktop/views/components/settings.tags.vue b/src/client/app/desktop/views/components/settings.tags.vue
index 3edd5fdd99..3df4a6e64b 100644
--- a/src/client/app/desktop/views/components/settings.tags.vue
+++ b/src/client/app/desktop/views/components/settings.tags.vue
@@ -1,15 +1,15 @@
 <template>
 <div class="vfcitkilproprqtbnpoertpsziierwzi">
-	<div v-for="timeline in timelines" class="timeline">
+	<div v-for="timeline in timelines" class="timeline" :key="timeline.id">
 		<ui-input v-model="timeline.title" @change="save">
 			<span>{{ $t('title') }}</span>
 		</ui-input>
-		<ui-textarea :value="timeline.query ? timeline.query.map(tags => tags.join(' ')).join('\n') : ''" @input="onQueryChange(timeline, $event)">
+		<ui-textarea :value="timeline.query ? timeline.query.map(tags => tags.join(' ')).join('\n') : ''" :pre="true" @input="onQueryChange(timeline, $event)">
 			<span>{{ $t('query') }}</span>
 		</ui-textarea>
-		<ui-button class="save" @click="save">{{ $t('save') }}</ui-button>
 	</div>
 	<ui-button class="add" @click="add">{{ $t('add') }}</ui-button>
+	<ui-button class="save" @click="save">{{ $t('save') }}</ui-button>
 </div>
 </template>
 
@@ -33,12 +33,19 @@ export default Vue.extend({
 				title: '',
 				query: ''
 			});
-
-			this.save();
 		},
 
 		save() {
-			this.$store.dispatch('settings/set', { key: 'tagTimelines', value: this.timelines });
+			const timelines = this.timelines
+				.filter(timeline => timeline.title)
+				.map(timeline => {
+					if (!(timeline.query && timeline.query[0] && timeline.query[0][0])) {
+						timeline.query = timeline.title.split('\n').map(tags => tags.split(' '));
+					}
+					return timeline;
+				});
+
+			this.$store.dispatch('settings/set', { key: 'tagTimelines', value: timelines });
 		},
 
 		onQueryChange(timeline, value) {