翻訳ファイルをランタイムで読み込み
This commit is contained in:
		
							parent
							
								
									ec4d5857d8
								
							
						
					
					
						commit
						84b488a912
					
				
					 6 changed files with 46 additions and 33 deletions
				
			
		
							
								
								
									
										15
									
								
								gulpfile.ts
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								gulpfile.ts
									
										
									
									
									
								
							|  | @ -2,6 +2,7 @@ | |||
|  * Gulp tasks | ||||
|  */ | ||||
| 
 | ||||
| import * as fs from 'fs'; | ||||
| import * as gulp from 'gulp'; | ||||
| import * as ts from 'gulp-typescript'; | ||||
| import * as rimraf from 'rimraf'; | ||||
|  | @ -31,6 +32,18 @@ gulp.task('build:copy:fonts', () => | |||
| 	gulp.src('./node_modules/three/examples/fonts/**/*').pipe(gulp.dest('./built/client/assets/fonts/')) | ||||
| ); | ||||
| 
 | ||||
| gulp.task('build:copy:locales', cb => { | ||||
| 	fs.mkdirSync('./built/client/assets/locales', { recursive: true }); | ||||
| 
 | ||||
| 	const v = { '_version_': meta.version }; | ||||
| 
 | ||||
| 	for (const [lang, locale] of Object.entries(locales)) { | ||||
| 		fs.writeFileSync(`./built/client/assets/locales/${lang}.${meta.version}.json`, JSON.stringify({ ...locale, ...v }), 'utf-8'); | ||||
| 	} | ||||
| 
 | ||||
| 	cb(); | ||||
| }); | ||||
| 
 | ||||
| gulp.task('build:client:script', () => { | ||||
| 	return gulp.src(['./src/server/web/boot.js']) | ||||
| 		.pipe(replace('VERSION', JSON.stringify(meta.version))) | ||||
|  | @ -47,7 +60,7 @@ gulp.task('build:client:style', () => { | |||
| 		.pipe(gulp.dest('./built/server/web/')); | ||||
| }); | ||||
| 
 | ||||
| gulp.task('build:copy', gulp.parallel('build:copy:views', 'build:client:script', 'build:client:style', 'build:copy:fonts', () => | ||||
| gulp.task('build:copy', gulp.parallel('build:copy:locales', 'build:copy:views', 'build:client:script', 'build:client:style', 'build:copy:fonts', () => | ||||
| 	gulp.src([ | ||||
| 		'./src/emojilist.json', | ||||
| 		'./src/server/web/views/**/*', | ||||
|  |  | |||
|  | @ -1,9 +1,7 @@ | |||
| { | ||||
| 	"globals": { | ||||
| 		"_DEV_": false, | ||||
| 		"_LANG_": false, | ||||
| 		"_LANGS_": false, | ||||
| 		"_LOCALE_": false, | ||||
| 		"_VERSION_": false, | ||||
| 		"_ENV_": false, | ||||
| 		"_PERF_PREFIX_": false, | ||||
|  |  | |||
							
								
								
									
										2
									
								
								src/client/@types/global.d.ts
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								src/client/@types/global.d.ts
									
										
									
									
										vendored
									
									
								
							|  | @ -1,6 +1,4 @@ | |||
| declare const _LANG_: string; | ||||
| declare const _LANGS_: string[][]; | ||||
| declare const _LOCALE_: Record<string, any>; | ||||
| declare const _VERSION_: string; | ||||
| declare const _ENV_: string; | ||||
| declare const _DEV_: boolean; | ||||
|  |  | |||
|  | @ -6,9 +6,9 @@ export const hostname = address.hostname; | |||
| export const url = address.origin; | ||||
| export const apiUrl = url + '/api'; | ||||
| export const wsUrl = url.replace('http://', 'ws://').replace('https://', 'wss://') + '/streaming'; | ||||
| export const lang = _LANG_; | ||||
| export const lang = localStorage.getItem('lang'); | ||||
| export const langs = _LANGS_; | ||||
| export const locale = _LOCALE_; // TODO: code splittingするため、翻訳ファイルを分割したうえでwebpackのimport alias使って読み込むようにしたい
 | ||||
| export const locale = JSON.parse(localStorage.getItem('locale')); | ||||
| export const version = _VERSION_; | ||||
| export const instanceName = siteName === 'Misskey' ? host : siteName; | ||||
| export const ui = localStorage.getItem('ui'); | ||||
|  |  | |||
|  | @ -1,7 +1,8 @@ | |||
| /** | ||||
|  * BOOT LOADER | ||||
|  * サーバーからレスポンスされるHTMLに埋め込まれるスクリプトで、以下の役割を持ちます。 | ||||
|  * - バージョンやユーザーの言語に基づいて適切なメインスクリプトを読み込む。 | ||||
|  * - 翻訳ファイルをフェッチする。 | ||||
|  * - バージョンに基づいて適切なメインスクリプトを読み込む。 | ||||
|  * - キャッシュされたコンパイル済みテーマを適用する。 | ||||
|  * - クライアントの設定値に基づいて対応するHTMLクラス等を設定する。 | ||||
|  * テーマをこの段階で設定するのは、メインスクリプトが読み込まれる間もテーマを適用したいためです。 | ||||
|  | @ -10,27 +11,34 @@ | |||
| 
 | ||||
| 'use strict'; | ||||
| 
 | ||||
| // ブロックの中に入れないと、定義した変数がブラウザのグローバルスコープに登録されてしまい邪魔
 | ||||
| { | ||||
| 	//#region Script
 | ||||
| // ブロックの中に入れないと、定義した変数がブラウザのグローバルスコープに登録されてしまい邪魔なので
 | ||||
| (async () => { | ||||
| 	const v = localStorage.getItem('v') || VERSION; | ||||
| 
 | ||||
| 	//#region Detect language
 | ||||
| 	const supportedLangs = LANGS; | ||||
| 	let lang = localStorage.getItem('lang'); | ||||
| 	if (lang == null || !supportedLangs.includes(lang)) { | ||||
| 		if (supportedLangs.includes(navigator.language)) { | ||||
| 			lang = navigator.language; | ||||
| 		} else { | ||||
| 			lang = supportedLangs.find(x => x.split('-')[0] === navigator.language); | ||||
| 	//#region Detect language & fetch translations
 | ||||
| 	if (localStorage.hasOwnProperty('locale')) { | ||||
| 		// TODO: 非同期でlocaleの更新処理をする
 | ||||
| 	} else { | ||||
| 		const supportedLangs = LANGS; | ||||
| 		let lang = localStorage.getItem('lang'); | ||||
| 		if (lang == null || !supportedLangs.includes(lang)) { | ||||
| 			if (supportedLangs.includes(navigator.language)) { | ||||
| 				lang = navigator.language; | ||||
| 			} else { | ||||
| 				lang = supportedLangs.find(x => x.split('-')[0] === navigator.language); | ||||
| 
 | ||||
| 			// Fallback
 | ||||
| 			if (lang == null) lang = 'en-US'; | ||||
| 				// Fallback
 | ||||
| 				if (lang == null) lang = 'en-US'; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		const res = await fetch(`/assets/locales/${lang}.${v}.json`); | ||||
| 		const json = await res.json(); | ||||
| 		localStorage.setItem('locale', JSON.stringify(json)); | ||||
| 	} | ||||
| 	//#endregion
 | ||||
| 
 | ||||
| 	const ver = localStorage.getItem('v') || VERSION; | ||||
| 
 | ||||
| 	//#region Script
 | ||||
| 	const salt = localStorage.getItem('salt') | ||||
| 		? `?salt=${localStorage.getItem('salt')}` | ||||
| 		: ''; | ||||
|  | @ -38,7 +46,7 @@ | |||
| 	const head = document.getElementsByTagName('head')[0]; | ||||
| 
 | ||||
| 	const script = document.createElement('script'); | ||||
| 	script.setAttribute('src', `/assets/app.${ver}.${lang}.js${salt}`); | ||||
| 	script.setAttribute('src', `/assets/app.${v}.js${salt}`); | ||||
| 	script.setAttribute('async', 'true'); | ||||
| 	script.setAttribute('defer', 'true'); | ||||
| 	head.appendChild(script); | ||||
|  | @ -56,7 +64,7 @@ | |||
| 
 | ||||
| 		const meta = await res.json(); | ||||
| 
 | ||||
| 		if (meta.version != ver) { | ||||
| 		if (meta.version != v) { | ||||
| 			localStorage.setItem('v', meta.version); | ||||
| 			alert( | ||||
| 				'Misskeyの新しいバージョンがあります。ページを再度読み込みします。' + | ||||
|  | @ -113,4 +121,4 @@ | |||
| 
 | ||||
| 		location.reload(); | ||||
| 	} | ||||
| } | ||||
| })(); | ||||
|  |  | |||
|  | @ -33,9 +33,7 @@ const postcss = { | |||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| module.exports = Object.keys(isProduction ? locales : { | ||||
| 	'ja-JP': locales['ja-JP'] | ||||
| }).map(lang => ({ | ||||
| module.exports = { | ||||
| 	entry: { | ||||
| 		app: './src/client/init.ts', | ||||
| 		sw: './src/client/sw/sw.ts' | ||||
|  | @ -133,9 +131,7 @@ module.exports = Object.keys(isProduction ? locales : { | |||
| 		new webpack.ProgressPlugin({}), | ||||
| 		new webpack.DefinePlugin({ | ||||
| 			_VERSION_: JSON.stringify(meta.version), | ||||
| 			_LANG_: JSON.stringify(lang), | ||||
| 			_LANGS_: JSON.stringify(Object.entries(locales).map(([k, v]: [string, any]) => [k, v._lang_])), | ||||
| 			_LOCALE_: JSON.stringify(locales[lang]), | ||||
| 			_ENV_: JSON.stringify(process.env.NODE_ENV), | ||||
| 			_DEV_: process.env.NODE_ENV !== 'production', | ||||
| 			_PERF_PREFIX_: JSON.stringify('Misskey:'), | ||||
|  | @ -153,7 +149,7 @@ module.exports = Object.keys(isProduction ? locales : { | |||
| 	], | ||||
| 	output: { | ||||
| 		path: __dirname + '/built/client/assets', | ||||
| 		filename: `[name].${meta.version}.${lang}.js`, | ||||
| 		filename: `[name].${meta.version}.js`, | ||||
| 		publicPath: `/assets/` | ||||
| 	}, | ||||
| 	resolve: { | ||||
|  | @ -173,4 +169,4 @@ module.exports = Object.keys(isProduction ? locales : { | |||
| 	}, | ||||
| 	devtool: false, //'source-map',
 | ||||
| 	mode: isProduction ? 'production' : 'development' | ||||
| })); | ||||
| }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue