diff --git a/locales/ja.yml b/locales/ja.yml
index 6f8b1eaf20..953556eedb 100644
--- a/locales/ja.yml
+++ b/locales/ja.yml
@@ -495,9 +495,6 @@ desktop/views/components/settings.vue:
   advanced-settings: "高度な設定"
   debug-mode: "デバッグモードを有効にする"
   debug-mode-desc: "この設定はブラウザに記憶されます。"
-  use-raw-script: "生のスクリプトを読み込む"
-  use-raw-script-desc: "圧縮されていない「生の」スクリプトを使用します。サイズが大きいため、読み込みに時間がかかる場合があります。この設定はブラウザに記憶されます。"
-  source-info: "Misskeyはソースマップも提供しています。"
   experimental: "実験的機能を有効にする"
   experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。"
   tools: "ツール"
diff --git a/package.json b/package.json
index 119d2dac53..14f7956f52 100644
--- a/package.json
+++ b/package.json
@@ -211,6 +211,7 @@
 		"vue-template-compiler": "2.5.16",
 		"vuedraggable": "2.16.0",
 		"vuex": "3.0.1",
+		"vuex-persistedstate": "^2.5.4",
 		"web-push": "3.3.1",
 		"webfinger.js": "2.6.6",
 		"webpack": "4.8.3",
diff --git a/src/client/app/boot.js b/src/client/app/boot.js
index 9338bc501e..e09a5d12e9 100644
--- a/src/client/app/boot.js
+++ b/src/client/app/boot.js
@@ -29,11 +29,21 @@
 	if (url.pathname == '/auth') app = 'auth';
 	//#endregion
 
-	// Detect the user language
-	// Note: The default language is Japanese
+	//#region Detect the user language
 	let lang = navigator.language.split('-')[0];
+
+	// The default language is English
 	if (!LANGS.includes(lang)) lang = 'en';
-	if (localStorage.getItem('lang')) lang = localStorage.getItem('lang');
+
+	const vuex = localStorage.getItem('vuex');
+	if (vuex) {
+		const data = JSON.parse(vuex);
+		if (data.device.lang) lang = data.device.lang;
+	}
+
+	const storedLang = localStorage.getItem('lang');
+	if (storedLang) lang = storedLang;
+	//#endregion
 
 	// Detect the user agent
 	const ua = navigator.userAgent.toLowerCase();
@@ -68,13 +78,6 @@
 	// Script version
 	const ver = localStorage.getItem('v') || VERSION;
 
-	// Whether in debug mode
-	const isDebug = localStorage.getItem('debug') == 'true';
-
-	// Whether use raw version script
-	const raw = (localStorage.getItem('useRawScript') == 'true' && isDebug)
-		|| ENV != 'production';
-
 	// Get salt query
 	const salt = localStorage.getItem('salt')
 		? '?salt=' + localStorage.getItem('salt')
@@ -84,7 +87,7 @@
 	// Note: 'async' make it possible to load the script asyncly.
 	//       'defer' make it possible to run the script when the dom loaded.
 	const script = document.createElement('script');
-	script.setAttribute('src', `/assets/${app}.${ver}.${lang}.${raw ? 'raw' : 'min'}.js${salt}`);
+	script.setAttribute('src', `/assets/${app}.${ver}.${lang}.js${salt}`);
 	script.setAttribute('async', 'true');
 	script.setAttribute('defer', 'true');
 	head.appendChild(script);
diff --git a/src/client/app/common/views/components/avatar.vue b/src/client/app/common/views/components/avatar.vue
index 8cc72fb518..6b407ccc80 100644
--- a/src/client/app/common/views/components/avatar.vue
+++ b/src/client/app/common/views/components/avatar.vue
@@ -22,7 +22,7 @@ export default Vue.extend({
 	},
 	computed: {
 		lightmode(): boolean {
-			return localStorage.getItem('lightmode') == 'true';
+			return this.$store.state.device.lightmode;
 		},
 		style(): any {
 			return {
diff --git a/src/client/app/common/views/components/messaging-room.vue b/src/client/app/common/views/components/messaging-room.vue
index 330834233a..7832a331df 100644
--- a/src/client/app/common/views/components/messaging-room.vue
+++ b/src/client/app/common/views/components/messaging-room.vue
@@ -149,9 +149,9 @@ export default Vue.extend({
 
 		onMessage(message) {
 			// サウンドを再生する
-			if ((this as any).os.isEnableSounds) {
+			if (this.$store.state.device.enableSounds) {
 				const sound = new Audio(`${url}/assets/message.mp3`);
-				sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5;
+				sound.volume = this.$store.state.device.soundVolume;
 				sound.play();
 			}
 
diff --git a/src/client/app/common/views/components/othello.game.vue b/src/client/app/common/views/components/othello.game.vue
index 8c646cce07..ea75558d10 100644
--- a/src/client/app/common/views/components/othello.game.vue
+++ b/src/client/app/common/views/components/othello.game.vue
@@ -162,9 +162,9 @@ export default Vue.extend({
 			this.o.put(this.myColor, pos);
 
 			// サウンドを再生する
-			if ((this as any).os.isEnableSounds) {
+			if (this.$store.state.device.enableSounds) {
 				const sound = new Audio(`${url}/assets/othello-put-me.mp3`);
-				sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5;
+				sound.volume = this.$store.state.device.soundVolume;
 				sound.play();
 			}
 
@@ -186,9 +186,9 @@ export default Vue.extend({
 			this.$forceUpdate();
 
 			// サウンドを再生する
-			if ((this as any).os.isEnableSounds && x.color != this.myColor) {
+			if (this.$store.state.device.enableSounds && x.color != this.myColor) {
 				const sound = new Audio(`${url}/assets/othello-put-you.mp3`);
-				sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5;
+				sound.volume = this.$store.state.device.soundVolume;
 				sound.play();
 			}
 		},
diff --git a/src/client/app/config.ts b/src/client/app/config.ts
index 522d7ff056..70c085de1c 100644
--- a/src/client/app/config.ts
+++ b/src/client/app/config.ts
@@ -8,6 +8,7 @@ declare const _STATS_URL_: string;
 declare const _STATUS_URL_: string;
 declare const _DEV_URL_: string;
 declare const _LANG_: string;
+declare const _LANGS_: string;
 declare const _RECAPTCHA_SITEKEY_: string;
 declare const _SW_PUBLICKEY_: string;
 declare const _THEME_COLOR_: string;
@@ -27,6 +28,7 @@ export const statsUrl = _STATS_URL_;
 export const statusUrl = _STATUS_URL_;
 export const devUrl = _DEV_URL_;
 export const lang = _LANG_;
+export const langs = _LANGS_;
 export const recaptchaSitekey = _RECAPTCHA_SITEKEY_;
 export const swPublickey = _SW_PUBLICKEY_;
 export const themeColor = _THEME_COLOR_;
diff --git a/src/client/app/desktop/views/components/home.vue b/src/client/app/desktop/views/components/home.vue
index 87dae5a806..d84c1e404f 100644
--- a/src/client/app/desktop/views/components/home.vue
+++ b/src/client/app/desktop/views/components/home.vue
@@ -102,7 +102,7 @@ export default Vue.extend({
 
 	computed: {
 		home(): any[] {
-			return this.$store.state.settings.data.home;
+			return this.$store.state.settings.home;
 		},
 		left(): any[] {
 			return this.home.filter(w => w.place == 'left');
diff --git a/src/client/app/desktop/views/components/notes.vue b/src/client/app/desktop/views/components/notes.vue
index c041e5278c..55b0de3fbd 100644
--- a/src/client/app/desktop/views/components/notes.vue
+++ b/src/client/app/desktop/views/components/notes.vue
@@ -145,9 +145,9 @@ export default Vue.extend({
 				this.notes.unshift(note);
 
 				// サウンドを再生する
-				if ((this as any).os.isEnableSounds && !silent) {
+				if (this.$store.state.device.enableSounds && !silent) {
 					const sound = new Audio(`${url}/assets/post.mp3`);
-					sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5;
+					sound.volume = this.$store.state.device.soundVolume;
 					sound.play();
 				}
 
diff --git a/src/client/app/desktop/views/components/settings.vue b/src/client/app/desktop/views/components/settings.vue
index 24af64a59c..3fe09b9acc 100644
--- a/src/client/app/desktop/views/components/settings.vue
+++ b/src/client/app/desktop/views/components/settings.vue
@@ -62,8 +62,10 @@
 			<el-slider
 				v-model="soundVolume"
 				:show-input="true"
-				:format-tooltip="v => `${v}%`"
+				:format-tooltip="v => `${v * 100}%`"
 				:disabled="!enableSounds"
+				:max="1"
+				:step="0.1"
 			/>
 			<button class="ui button" @click="soundTest">%fa:volume-up% %i18n:@test%</button>
 		</section>
@@ -77,14 +79,10 @@
 			<h1>%i18n:@language%</h1>
 			<el-select v-model="lang" placeholder="%i18n:@pick-language%">
 				<el-option-group label="%i18n:@recommended%">
-					<el-option label="%i18n:@auto%" value=""/>
+					<el-option label="%i18n:@auto%" :value="null"/>
 				</el-option-group>
 				<el-option-group label="%i18n:@specify-language%">
-					<el-option label="日本語" value="ja"/>
-					<el-option label="English" value="en"/>
-					<el-option label="Français" value="fr"/>
-					<el-option label="Polski" value="pl"/>
-					<el-option label="Deutsch" value="de"/>
+					<el-option v-for="x in langs" :label="x[1]" :value="x[0]" :key="x[0]"/>
 				</el-option-group>
 			</el-select>
 			<div class="none ui info">
@@ -178,15 +176,7 @@
 			<mk-switch v-model="debug" text="%i18n:@debug-mode%">
 				<span>%i18n:@debug-mode-desc%</span>
 			</mk-switch>
-			<template v-if="debug">
-				<mk-switch v-model="useRawScript" text="%i18n:@use-raw-script%">
-					<span>%i18n:@use-raw-script-desc%</span>
-				</mk-switch>
-				<div class="none ui info">
-				<p>%fa:info-circle%%i18n:@source-info%</p>
-			</div>
-			</template>
-			<mk-switch v-model="enableExperimental" text="%i18n:@experimental%">
+			<mk-switch v-model="enableExperimentalFeatures" text="%i18n:@experimental%">
 				<span>%i18n:@experimental-desc%</span>
 			</mk-switch>
 			<details v-if="debug">
@@ -214,7 +204,7 @@ import XApi from './settings.api.vue';
 import XApps from './settings.apps.vue';
 import XSignins from './settings.signins.vue';
 import XDrive from './settings.drive.vue';
-import { url, docsUrl, license, lang, version } from '../../../config';
+import { url, docsUrl, license, lang, langs, version } from '../../../config';
 import checkForUpdate from '../../../common/scripts/check-for-update';
 import MkTaskManager from './taskmanager.vue';
 
@@ -235,55 +225,60 @@ export default Vue.extend({
 			meta: null,
 			license,
 			version,
+			langs,
 			latestVersion: undefined,
 			checkingForUpdate: false,
-			darkmode: localStorage.getItem('darkmode') == 'true',
-			enableSounds: localStorage.getItem('enableSounds') == 'true',
-			autoPopout: localStorage.getItem('autoPopout') == 'true',
-			apiViaStream: localStorage.getItem('apiViaStream') ? localStorage.getItem('apiViaStream') == 'true' : true,
-			soundVolume: localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) : 50,
-			lang: localStorage.getItem('lang') || '',
-			preventUpdate: localStorage.getItem('preventUpdate') == 'true',
-			debug: localStorage.getItem('debug') == 'true',
-			useRawScript: localStorage.getItem('useRawScript') == 'true',
-			enableExperimental: localStorage.getItem('enableExperimental') == 'true'
+			darkmode: localStorage.getItem('darkmode') == 'true'
 		};
 	},
 	computed: {
 		licenseUrl(): string {
 			return `${docsUrl}/${lang}/license`;
+		},
+
+		apiViaStream: {
+			get() { return this.$store.state.device.apiViaStream; },
+			set(value) { this.$store.commit('device/set', { key: 'apiViaStream', value }); }
+		},
+
+		autoPopout: {
+			get() { return this.$store.state.device.autoPopout; },
+			set(value) { this.$store.commit('device/set', { key: 'autoPopout', value }); }
+		},
+
+		enableSounds: {
+			get() { return this.$store.state.device.enableSounds; },
+			set(value) { this.$store.commit('device/set', { key: 'enableSounds', value }); }
+		},
+
+		soundVolume: {
+			get() { return this.$store.state.device.soundVolume; },
+			set(value) { this.$store.commit('device/set', { key: 'soundVolume', value }); }
+		},
+
+		lang: {
+			get() { return this.$store.state.device.lang; },
+			set(value) { this.$store.commit('device/set', { key: 'lang', value }); }
+		},
+
+		preventUpdate: {
+			get() { return this.$store.state.device.preventUpdate; },
+			set(value) { this.$store.commit('device/set', { key: 'preventUpdate', value }); }
+		},
+
+		debug: {
+			get() { return this.$store.state.device.debug; },
+			set(value) { this.$store.commit('device/set', { key: 'debug', value }); }
+		},
+
+		enableExperimentalFeatures: {
+			get() { return this.$store.state.device.enableExperimentalFeatures; },
+			set(value) { this.$store.commit('device/set', { key: 'enableExperimentalFeatures', value }); }
 		}
 	},
 	watch: {
-		autoPopout() {
-			localStorage.setItem('autoPopout', this.autoPopout ? 'true' : 'false');
-		},
-		apiViaStream() {
-			localStorage.setItem('apiViaStream', this.apiViaStream ? 'true' : 'false');
-		},
 		darkmode() {
 			(this as any)._updateDarkmode_(this.darkmode);
-		},
-		enableSounds() {
-			localStorage.setItem('enableSounds', this.enableSounds ? 'true' : 'false');
-		},
-		soundVolume() {
-			localStorage.setItem('soundVolume', this.soundVolume.toString());
-		},
-		lang() {
-			localStorage.setItem('lang', this.lang);
-		},
-		preventUpdate() {
-			localStorage.setItem('preventUpdate', this.preventUpdate ? 'true' : 'false');
-		},
-		debug() {
-			localStorage.setItem('debug', this.debug ? 'true' : 'false');
-		},
-		useRawScript() {
-			localStorage.setItem('useRawScript', this.useRawScript ? 'true' : 'false');
-		},
-		enableExperimental() {
-			localStorage.setItem('enableExperimental', this.enableExperimental ? 'true' : 'false');
 		}
 	},
 	created() {
@@ -391,7 +386,7 @@ export default Vue.extend({
 		},
 		soundTest() {
 			const sound = new Audio(`${url}/assets/message.mp3`);
-			sound.volume = localStorage.getItem('soundVolume') ? parseInt(localStorage.getItem('soundVolume'), 10) / 100 : 0.5;
+			sound.volume = this.$store.state.device.soundVolume;
 			sound.play();
 		}
 	}
diff --git a/src/client/app/desktop/views/components/window.vue b/src/client/app/desktop/views/components/window.vue
index ac84c2bd62..7ee1da12ba 100644
--- a/src/client/app/desktop/views/components/window.vue
+++ b/src/client/app/desktop/views/components/window.vue
@@ -95,7 +95,7 @@ export default Vue.extend({
 	},
 
 	created() {
-		if (localStorage.getItem('autoPopout') == 'true' && this.popoutUrl) {
+		if (this.$store.state.device.autoPopout && this.popoutUrl) {
 			this.popout();
 			this.preventMount = true;
 		} else {
diff --git a/src/client/app/init.ts b/src/client/app/init.ts
index fd04f9bcc3..34bc6a2785 100644
--- a/src/client/app/init.ts
+++ b/src/client/app/init.ts
@@ -147,7 +147,7 @@ export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API)
 						os,
 						api: os.api,
 						apis: os.apis,
-						clientSettings: os.store.state.settings.data
+						clientSettings: os.store.state.settings
 					};
 				}
 			});
@@ -173,7 +173,7 @@ export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API)
 		}
 
 		//#region 更新チェック
-		const preventUpdate = localStorage.getItem('preventUpdate') == 'true';
+		const preventUpdate = os.store.state.device.preventUpdate;
 		if (!preventUpdate) {
 			setTimeout(() => {
 				checkForUpdate(os);
diff --git a/src/client/app/mios.ts b/src/client/app/mios.ts
index 2373b0d8d2..a5a38a5414 100644
--- a/src/client/app/mios.ts
+++ b/src/client/app/mios.ts
@@ -98,14 +98,7 @@ export default class MiOS extends EventEmitter {
 	 * Whether is debug mode
 	 */
 	public get debug() {
-		return localStorage.getItem('debug') == 'true';
-	}
-
-	/**
-	 * Whether enable sounds
-	 */
-	public get isEnableSounds() {
-		return localStorage.getItem('enableSounds') == 'true';
+		return this.store ? this.store.state.device.debug : false;
 	}
 
 	public store: ReturnType<typeof initStore>;
@@ -435,12 +428,8 @@ export default class MiOS extends EventEmitter {
 			});
 		});
 
-		// Whether use raw version script
-		const raw = (localStorage.getItem('useRawScript') == 'true' && this.debug)
-			|| process.env.NODE_ENV != 'production';
-
 		// The path of service worker script
-		const sw = `/sw.${version}.${lang}.${raw ? 'raw' : 'min'}.js`;
+		const sw = `/sw.${version}.${lang}.js`;
 
 		// Register service worker
 		navigator.serviceWorker.register(sw).then(registration => {
@@ -471,8 +460,7 @@ export default class MiOS extends EventEmitter {
 		};
 
 		const promise = new Promise((resolve, reject) => {
-			const viaStream = this.stream && this.stream.hasConnection &&
-				(localStorage.getItem('apiViaStream') ? localStorage.getItem('apiViaStream') == 'true' : true);
+			const viaStream = this.stream && this.stream.hasConnection && this.store.state.device.apiViaStream;
 
 			if (viaStream) {
 				const stream = this.stream.borrow();
diff --git a/src/client/app/mobile/views/components/media-image.vue b/src/client/app/mobile/views/components/media-image.vue
index d4ee0c66a9..c4622b01a7 100644
--- a/src/client/app/mobile/views/components/media-image.vue
+++ b/src/client/app/mobile/views/components/media-image.vue
@@ -17,7 +17,7 @@ export default Vue.extend({
 	},
 	computed: {
 		lightmode(): boolean {
-			return localStorage.getItem('lightmode') == 'true';
+			return this.$store.state.device.lightmode;
 		},
 		style(): any {
 			return {
diff --git a/src/client/app/mobile/views/pages/settings.vue b/src/client/app/mobile/views/pages/settings.vue
index 55c7895a90..3b0df87549 100644
--- a/src/client/app/mobile/views/pages/settings.vue
+++ b/src/client/app/mobile/views/pages/settings.vue
@@ -71,11 +71,7 @@
 							</md-optgroup>
 
 							<md-optgroup label="%i18n:@specify-language%">
-								<md-option value="ja">日本語</md-option>
-								<md-option value="en">English</md-option>
-								<md-option value="fr">Français</md-option>
-								<md-option value="pl">Polski</md-option>
-								<md-option value="de">Deutsch</md-option>
+								<md-option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</md-option>
 							</md-optgroup>
 						</md-select>
 					</md-field>
@@ -122,7 +118,7 @@
 
 <script lang="ts">
 import Vue from 'vue';
-import { apiUrl, version, codename } from '../../../config';
+import { apiUrl, version, codename, langs } from '../../../config';
 import checkForUpdate from '../../../common/scripts/check-for-update';
 
 import XProfile from './settings/settings.profile.vue';
@@ -137,9 +133,8 @@ export default Vue.extend({
 			apiUrl,
 			version,
 			codename,
+			langs,
 			darkmode: localStorage.getItem('darkmode') == 'true',
-			lightmode: localStorage.getItem('lightmode') == 'true',
-			lang: localStorage.getItem('lang') || '',
 			latestVersion: undefined,
 			checkingForUpdate: false
 		};
@@ -148,20 +143,22 @@ export default Vue.extend({
 	computed: {
 		name(): string {
 			return Vue.filter('userName')((this as any).os.i);
-		}
+		},
+
+		lightmode: {
+			get() { return this.$store.state.device.lightmode; },
+			set(value) { this.$store.commit('device/set', { key: 'lightmode', value }); }
+		},
+
+		lang: {
+			get() { return this.$store.state.device.lang; },
+			set(value) { this.$store.commit('device/set', { key: 'lang', value }); }
+		},
 	},
 
 	watch: {
 		darkmode() {
 			(this as any)._updateDarkmode_(this.darkmode);
-		},
-
-		lightmode() {
-			localStorage.setItem('lightmode', this.lightmode);
-		},
-
-		lang() {
-			localStorage.setItem('lang', this.lang);
 		}
 	},
 
diff --git a/src/client/app/mobile/views/pages/widgets.vue b/src/client/app/mobile/views/pages/widgets.vue
index f0a0877862..03abcabe8f 100644
--- a/src/client/app/mobile/views/pages/widgets.vue
+++ b/src/client/app/mobile/views/pages/widgets.vue
@@ -65,7 +65,7 @@ export default Vue.extend({
 
 	computed: {
 		widgets(): any[] {
-			return this.$store.state.settings.data.mobileHome;
+			return this.$store.state.settings.mobileHome;
 		}
 	},
 
diff --git a/src/client/app/store.ts b/src/client/app/store.ts
index 1f1189054d..dceb51f2f3 100644
--- a/src/client/app/store.ts
+++ b/src/client/app/store.ts
@@ -1,4 +1,6 @@
 import Vuex from 'vuex';
+import createPersistedState from 'vuex-persistedstate';
+
 import MiOS from './mios';
 
 const defaultSettings = {
@@ -14,14 +16,28 @@ const defaultSettings = {
 	showRenotedMyNotes: true
 };
 
+const defaultDeviceSettings = {
+	apiViaStream: true,
+	autoPopout: false,
+	enableSounds: true,
+	soundVolume: 0.5,
+	lang: null,
+	preventUpdate: false,
+	debug: false,
+	lightmode: false,
+};
+
 export default (os: MiOS) => new Vuex.Store({
 	plugins: [store => {
 		store.subscribe((mutation, state) => {
 			if (mutation.type.startsWith('settings/')) {
-				localStorage.setItem('settings', JSON.stringify(state.settings.data));
+				localStorage.setItem('settings', JSON.stringify(state.settings));
 			}
 		});
-	}],
+	}, createPersistedState({
+		paths: ['device'],
+		filter: mut => mut.type.startsWith('device/')
+	})],
 
 	state: {
 		indicate: false,
@@ -39,50 +55,60 @@ export default (os: MiOS) => new Vuex.Store({
 	},
 
 	modules: {
-		settings: {
+		device: {
 			namespaced: true,
 
-			state: {
-				data: defaultSettings
-			},
+			state: defaultDeviceSettings,
 
 			mutations: {
 				set(state, x: { key: string; value: any }) {
-					state.data[x.key] = x.value;
+					state[x.key] = x.value;
+				}
+			}
+		},
+
+		settings: {
+			namespaced: true,
+
+			state: defaultSettings,
+
+			mutations: {
+				set(state, x: { key: string; value: any }) {
+					state[x.key] = x.value;
 				},
 
 				setHome(state, data) {
-					state.data.home = data;
+					state.home = data;
 				},
 
 				setHomeWidget(state, x) {
-					const w = state.data.home.find(w => w.id == x.id);
+					const w = state.home.find(w => w.id == x.id);
 					if (w) {
 						w.data = x.data;
 					}
 				},
 
 				addHomeWidget(state, widget) {
-					state.data.home.unshift(widget);
+					state.home.unshift(widget);
 				},
 
 				setMobileHome(state, data) {
-					state.data.mobileHome = data;
+					state.mobileHome = data;
 				},
 
 				setMobileHomeWidget(state, x) {
-					const w = state.data.mobileHome.find(w => w.id == x.id);
+					const w = state.mobileHome.find(w => w.id == x.id);
 					if (w) {
 						w.data = x.data;
 					}
 				},
 
 				addMobileHomeWidget(state, widget) {
-					state.data.mobileHome.unshift(widget);
+					state.mobileHome.unshift(widget);
 				},
 
 				removeMobileHomeWidget(state, widget) {
-					state.data.mobileHome = state.data.mobileHome.filter(w => w.id != widget.id);
+					state.mobileHome = state.mobileHome.filter(w => w.id != widget.id);
 				}
 			},
 
@@ -108,7 +134,7 @@ export default (os: MiOS) => new Vuex.Store({
 					ctx.commit('addHomeWidget', widget);
 
 					os.api('i/update_home', {
-						home: ctx.state.data.home
+						home: ctx.state.home
 					});
 				},
 
@@ -116,7 +142,7 @@ export default (os: MiOS) => new Vuex.Store({
 					ctx.commit('addMobileHomeWidget', widget);
 
 					os.api('i/update_mobile_home', {
-						home: ctx.state.data.mobileHome
+						home: ctx.state.mobileHome
 					});
 				},
 
@@ -124,7 +150,7 @@ export default (os: MiOS) => new Vuex.Store({
 					ctx.commit('removeMobileHomeWidget', widget);
 
 					os.api('i/update_mobile_home', {
-						home: ctx.state.data.mobileHome.filter(w => w.id != widget.id)
+						home: ctx.state.mobileHome.filter(w => w.id != widget.id)
 					});
 				}
 			}
diff --git a/webpack.config.ts b/webpack.config.ts
index 3aeecbd8a7..cd3a144b26 100644
--- a/webpack.config.ts
+++ b/webpack.config.ts
@@ -60,7 +60,7 @@ const entry = {
 
 const output = {
 	path: __dirname + '/built/client/assets',
-	filename: `[name].${version}.-.${isProduction ? 'min' : 'raw'}.js`
+	filename: `[name].${version}.-.js`
 };
 
 //#region Define consts
@@ -78,6 +78,7 @@ const consts = {
 	_WS_URL_: config.ws_url,
 	_DEV_URL_: config.dev_url,
 	_LANG_: '%lang%',
+	_LANGS_: Object.keys(locales).map(l => [l, locales[l].meta.lang]),
 	_HOST_: config.host,
 	_HOSTNAME_: config.hostname,
 	_URL_: config.url,
@@ -110,14 +111,14 @@ const plugins = [
 		//#region i18n
 		langs.forEach(lang => {
 			Object.keys(entry).forEach(file => {
-				let src = fs.readFileSync(`${__dirname}/built/client/assets/${file}.${version}.-.${isProduction ? 'min' : 'raw'}.js`, 'utf-8');
+				let src = fs.readFileSync(`${__dirname}/built/client/assets/${file}.${version}.-.js`, 'utf-8');
 
 				const i18nReplacer = new I18nReplacer(lang);
 
 				src = src.replace(i18nReplacer.pattern, i18nReplacer.replacement);
 				src = src.replace('%lang%', lang);
 
-				fs.writeFileSync(`${__dirname}/built/client/assets/${file}.${version}.${lang}.${isProduction ? 'min' : 'raw'}.js`, src, 'utf-8');
+				fs.writeFileSync(`${__dirname}/built/client/assets/${file}.${version}.${lang}.js`, src, 'utf-8');
 			});
 		});
 		//#endregion