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