This commit is contained in:
		
							parent
							
								
									05dd381502
								
							
						
					
					
						commit
						14f7ff13ec
					
				
					 4 changed files with 229 additions and 207 deletions
				
			
		|  | @ -14,7 +14,7 @@ const langs = { | |||
| 	'en': loadLang('en'), | ||||
| 	'fr': loadLang('fr'), | ||||
| 	'ja': native, | ||||
|  'pl': loadLang('pl') | ||||
| 	'pl': loadLang('pl') | ||||
| }; | ||||
| 
 | ||||
| Object.entries(langs).map(([, locale]) => { | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ import locale from '../../locales'; | |||
| export default class Replacer { | ||||
| 	private lang: string; | ||||
| 
 | ||||
| 	public pattern = /%i18n:([a-z0-9_\-@\.\!]+?)%/g; | ||||
| 	public pattern = /%i18n:([a-z0-9_\-\.\!]+?)%/g; | ||||
| 
 | ||||
| 	constructor(lang: string) { | ||||
| 		this.lang = lang; | ||||
|  | @ -53,23 +53,20 @@ export default class Replacer { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public replacement(ctx, match, key) { | ||||
| 		const client = '/src/client/app/'; | ||||
| 		let name = null; | ||||
| 	public replacement(match, key) { | ||||
| 		let path = null; | ||||
| 
 | ||||
| 		const shouldEscape = key[0] == '!'; | ||||
| 		if (shouldEscape) { | ||||
| 			key = key.substr(1); | ||||
| 		} | ||||
| 
 | ||||
| 		if (key[0] == '@') { | ||||
| 			name = ctx.src.substr(ctx.src.indexOf(client) + client.length); | ||||
| 			key = key.substr(1); | ||||
| 		if (key.indexOf('|') != -1) { | ||||
| 			path = key.split('|')[0]; | ||||
| 			key = key.split('|')[1]; | ||||
| 		} | ||||
| 
 | ||||
| 		if (ctx && ctx.lang) this.lang = ctx.lang; | ||||
| 
 | ||||
| 		const txt = this.get(name, key); | ||||
| 		const txt = this.get(path, key); | ||||
| 
 | ||||
| 		return shouldEscape | ||||
| 			? txt.replace(/'/g, '\\x27').replace(/"/g, '\\x22') | ||||
|  |  | |||
|  | @ -11,8 +11,10 @@ const minifyHtml = require('html-minifier').minify; | |||
| const WebpackOnBuildPlugin = require('on-build-webpack'); | ||||
| //const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
 | ||||
| const ProgressBarPlugin = require('progress-bar-webpack-plugin'); | ||||
| const I18nPlugin = require('webpack-multilang-i18n-plugin'); | ||||
| 
 | ||||
| import I18nReplacer from './src/build/i18n'; | ||||
| import { pattern as i18nPattern, replacement as i18nReplacement } from './webpack/i18n'; | ||||
| import { pattern as faPattern, replacement as faReplacement } from './src/build/fa'; | ||||
| const constants = require('./src/const.json'); | ||||
| import config from './src/config'; | ||||
|  | @ -37,183 +39,155 @@ global['collapseSpacesReplacement'] = html => { | |||
| global['base64replacement'] = (_, key) => { | ||||
| 	return fs.readFileSync(__dirname + '/src/client/' + key, 'base64'); | ||||
| }; | ||||
| 
 | ||||
| global['i18nReplacement'] = i18nReplacement; | ||||
| 
 | ||||
| //#endregion
 | ||||
| 
 | ||||
| const langs = Object.keys(locales); | ||||
| 
 | ||||
| // 無圧縮スクリプトを用意するのは重いので一時的に無効化
 | ||||
| //const entries = process.env.NODE_ENV == 'production'
 | ||||
| //	? langs.map(l => [l, false]).concat(langs.map(l => [l, true]))
 | ||||
| //	: langs.map(l => [l, false]);
 | ||||
| const entries = process.env.NODE_ENV == 'production' | ||||
| 	? langs.map(l => [l, true]) | ||||
| 	: langs.map(l => [l, false]); | ||||
| const isProduction = process.env.NODE_ENV == 'production'; | ||||
| 
 | ||||
| module.exports = entries.map(x => { | ||||
| 	const [lang, isProduction] = x; | ||||
| // Entries
 | ||||
| const entry = { | ||||
| 	desktop: './src/client/app/desktop/script.ts', | ||||
| 	mobile: './src/client/app/mobile/script.ts', | ||||
| 	//stats: './src/client/app/stats/script.ts',
 | ||||
| 	//status: './src/client/app/status/script.ts',
 | ||||
| 	dev: './src/client/app/dev/script.ts', | ||||
| 	auth: './src/client/app/auth/script.ts', | ||||
| 	sw: './src/client/app/sw.js' | ||||
| }; | ||||
| 
 | ||||
| 	// Chunk name
 | ||||
| 	const name = lang; | ||||
| const output = { | ||||
| 	path: __dirname + '/built/client/assets', | ||||
| 	filename: `[name].${version}.-.${isProduction ? 'min' : 'raw'}.js` | ||||
| }; | ||||
| 
 | ||||
| 	// Entries
 | ||||
| 	const entry = { | ||||
| 		desktop: './src/client/app/desktop/script.ts', | ||||
| 		mobile: './src/client/app/mobile/script.ts', | ||||
| 		//ch: './src/client/app/ch/script.ts',
 | ||||
| 		//stats: './src/client/app/stats/script.ts',
 | ||||
| 		//status: './src/client/app/status/script.ts',
 | ||||
| 		dev: './src/client/app/dev/script.ts', | ||||
| 		auth: './src/client/app/auth/script.ts', | ||||
| 		sw: './src/client/app/sw.js' | ||||
| 	}; | ||||
| //#region Define consts
 | ||||
| const consts = { | ||||
| 	_RECAPTCHA_SITEKEY_: config.recaptcha.site_key, | ||||
| 	_SW_PUBLICKEY_: config.sw ? config.sw.public_key : null, | ||||
| 	_THEME_COLOR_: constants.themeColor, | ||||
| 	_COPYRIGHT_: constants.copyright, | ||||
| 	_VERSION_: version, | ||||
| 	_CODENAME_: codename, | ||||
| 	_STATUS_URL_: config.status_url, | ||||
| 	_STATS_URL_: config.stats_url, | ||||
| 	_DOCS_URL_: config.docs_url, | ||||
| 	_API_URL_: config.api_url, | ||||
| 	_WS_URL_: config.ws_url, | ||||
| 	_DEV_URL_: config.dev_url, | ||||
| 	_LANG_: '%lang%', | ||||
| 	_HOST_: config.host, | ||||
| 	_HOSTNAME_: config.hostname, | ||||
| 	_URL_: config.url, | ||||
| 	_LICENSE_: licenseHtml, | ||||
| 	_GOOGLE_MAPS_API_KEY_: config.google_maps_api_key | ||||
| }; | ||||
| 
 | ||||
| 	const output = { | ||||
| 		path: __dirname + '/built/client/assets', | ||||
| 		filename: `[name].${version}.${lang}.${isProduction ? 'min' : 'raw'}.js` | ||||
| 	}; | ||||
| const _consts = {}; | ||||
| 
 | ||||
| 	const i18nReplacer = new I18nReplacer(lang as string); | ||||
| 	global['i18nReplacement'] = i18nReplacer.replacement; | ||||
| Object.keys(consts).forEach(key => { | ||||
| 	_consts[key] = JSON.stringify(consts[key]); | ||||
| }); | ||||
| //#endregion
 | ||||
| 
 | ||||
| 	//#region Define consts
 | ||||
| 	const consts = { | ||||
| 		_RECAPTCHA_SITEKEY_: config.recaptcha.site_key, | ||||
| 		_SW_PUBLICKEY_: config.sw ? config.sw.public_key : null, | ||||
| 		_THEME_COLOR_: constants.themeColor, | ||||
| 		_COPYRIGHT_: constants.copyright, | ||||
| 		_VERSION_: version, | ||||
| 		_CODENAME_: codename, | ||||
| 		_STATUS_URL_: config.status_url, | ||||
| 		_STATS_URL_: config.stats_url, | ||||
| 		_DOCS_URL_: config.docs_url, | ||||
| 		_API_URL_: config.api_url, | ||||
| 		_WS_URL_: config.ws_url, | ||||
| 		_DEV_URL_: config.dev_url, | ||||
| 		_LANG_: lang, | ||||
| 		_HOST_: config.host, | ||||
| 		_HOSTNAME_: config.hostname, | ||||
| 		_URL_: config.url, | ||||
| 		_LICENSE_: licenseHtml, | ||||
| 		_GOOGLE_MAPS_API_KEY_: config.google_maps_api_key | ||||
| 	}; | ||||
| const plugins = [ | ||||
| 	//new HardSourceWebpackPlugin(),
 | ||||
| 	new ProgressBarPlugin({ | ||||
| 		format: chalk`  {cyan.bold yes we can} {bold [}:bar{bold ]} {green.bold :percent} {gray (:current/:total)} :elapseds`, | ||||
| 		clear: false | ||||
| 	}), | ||||
| 	new webpack.DefinePlugin(_consts), | ||||
| 	new webpack.DefinePlugin({ | ||||
| 		'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development') | ||||
| 	}), | ||||
| 	new WebpackOnBuildPlugin(stats => { | ||||
| 		fs.writeFileSync('./built/client/meta.json', JSON.stringify({ | ||||
| 			version | ||||
| 		}), 'utf-8'); | ||||
| 
 | ||||
| 	const _consts = {}; | ||||
| 		//#region i18n
 | ||||
| 		langs.forEach(lang => { | ||||
| 			Object.keys(entry).forEach(file => { | ||||
| 				let src = fs.readFileSync(`${__dirname}/built/client/assets/${file}.${version}.-.${isProduction ? 'min' : 'raw'}.js`, 'utf8'); | ||||
| 
 | ||||
| 	Object.keys(consts).forEach(key => { | ||||
| 		_consts[key] = JSON.stringify(consts[key]); | ||||
| 	}); | ||||
| 	//#endregion
 | ||||
| 				const i18nReplacer = new I18nReplacer(lang); | ||||
| 
 | ||||
| 	const plugins = [ | ||||
| 		//new HardSourceWebpackPlugin(),
 | ||||
| 		new ProgressBarPlugin({ | ||||
| 			format: chalk`  {cyan.bold yes we can} {bold [}:bar{bold ]} {green.bold :percent} {gray (:current/:total)} :elapseds`, | ||||
| 			clear: false | ||||
| 		}), | ||||
| 		new webpack.DefinePlugin(_consts), | ||||
| 		new webpack.DefinePlugin({ | ||||
| 			'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development') | ||||
| 		}), | ||||
| 		new WebpackOnBuildPlugin(stats => { | ||||
| 			fs.writeFileSync('./built/client/meta.json', JSON.stringify({ | ||||
| 				version | ||||
| 			}), 'utf-8'); | ||||
| 		}), | ||||
| 		new VueLoaderPlugin() | ||||
| 	]; | ||||
| 				src = src.replace(i18nReplacer.pattern, i18nReplacer.replacement); | ||||
| 				src = src.replace('%lang%', lang); | ||||
| 
 | ||||
| 	if (isProduction) { | ||||
| 		plugins.push(new webpack.optimize.ModuleConcatenationPlugin()); | ||||
| 	} | ||||
| 				fs.writeFileSync(`${__dirname}/built/client/assets/${file}.${version}.${lang}.${isProduction ? 'min' : 'raw'}.js`, src, 'utf8'); | ||||
| 			}); | ||||
| 		}); | ||||
| 		//#endregion
 | ||||
| 	}), | ||||
| 	new VueLoaderPlugin(), | ||||
| 	new I18nPlugin() | ||||
| ]; | ||||
| 
 | ||||
| 	return { | ||||
| 		name, | ||||
| 		entry, | ||||
| 		module: { | ||||
| 			rules: [{ | ||||
| 				test: /\.vue$/, | ||||
| 				exclude: /node_modules/, | ||||
| 				use: [{ | ||||
| 					loader: 'vue-loader', | ||||
| 					options: { | ||||
| 						cssSourceMap: false, | ||||
| 						compilerOptions: { | ||||
| 							preserveWhitespace: false | ||||
| 						} | ||||
| if (isProduction) { | ||||
| 	plugins.push(new webpack.optimize.ModuleConcatenationPlugin()); | ||||
| } | ||||
| 
 | ||||
| module.exports = { | ||||
| 	entry, | ||||
| 	module: { | ||||
| 		rules: [{ | ||||
| 			test: /\.vue$/, | ||||
| 			exclude: /node_modules/, | ||||
| 			use: [{ | ||||
| 				loader: 'vue-loader', | ||||
| 				options: { | ||||
| 					cssSourceMap: false, | ||||
| 					compilerOptions: { | ||||
| 						preserveWhitespace: false | ||||
| 					} | ||||
| 				}, { | ||||
| 					loader: 'replace', | ||||
| 					query: { | ||||
| 						search: /%base64:(.+?)%/g.toString(), | ||||
| 						replace: 'base64replacement' | ||||
| 					} | ||||
| 				}, { | ||||
| 					loader: 'replace', | ||||
| 					query: { | ||||
| 						search: i18nReplacer.pattern.toString(), | ||||
| 						replace: 'i18nReplacement', | ||||
| 						i18n: true, | ||||
| 						lang | ||||
| 					} | ||||
| 				}, { | ||||
| 					loader: 'replace', | ||||
| 					query: { | ||||
| 						search: faPattern.toString(), | ||||
| 						replace: 'faReplacement' | ||||
| 					} | ||||
| 				}, { | ||||
| 					loader: 'replace', | ||||
| 					query: { | ||||
| 						search: /^<template>([\s\S]+?)\r?\n<\/template>/.toString(), | ||||
| 						replace: 'collapseSpacesReplacement' | ||||
| 					} | ||||
| 				}] | ||||
| 				} | ||||
| 			}, { | ||||
| 				test: /\.styl(us)?$/, | ||||
| 				exclude: /node_modules/, | ||||
| 				oneOf: [{ | ||||
| 					resourceQuery: /module/, | ||||
| 					use: [{ | ||||
| 						loader: 'vue-style-loader' | ||||
| 					}, { | ||||
| 						loader: 'css-loader', | ||||
| 						options: { | ||||
| 							modules: true, | ||||
| 							minimize: true | ||||
| 						} | ||||
| 					}, { | ||||
| 						loader: 'stylus-loader' | ||||
| 					}] | ||||
| 				}, { | ||||
| 					use: [{ | ||||
| 						loader: 'vue-style-loader' | ||||
| 					}, { | ||||
| 						loader: 'css-loader', | ||||
| 						options: { | ||||
| 							minimize: true | ||||
| 						} | ||||
| 					}, { | ||||
| 						loader: 'stylus-loader' | ||||
| 					}] | ||||
| 				}] | ||||
| 				loader: 'replace', | ||||
| 				query: { | ||||
| 					search: /%base64:(.+?)%/g.toString(), | ||||
| 					replace: 'base64replacement' | ||||
| 				} | ||||
| 			}, { | ||||
| 				test: /\.scss$/, | ||||
| 				exclude: /node_modules/, | ||||
| 				loader: 'replace', | ||||
| 				query: { | ||||
| 					search: i18nPattern.toString(), | ||||
| 					replace: 'i18nReplacement', | ||||
| 					i18n: true | ||||
| 				} | ||||
| 			}, { | ||||
| 				loader: 'replace', | ||||
| 				query: { | ||||
| 					search: faPattern.toString(), | ||||
| 					replace: 'faReplacement' | ||||
| 				} | ||||
| 			}, { | ||||
| 				loader: 'replace', | ||||
| 				query: { | ||||
| 					search: /^<template>([\s\S]+?)\r?\n<\/template>/.toString(), | ||||
| 					replace: 'collapseSpacesReplacement' | ||||
| 				} | ||||
| 			}] | ||||
| 		}, { | ||||
| 			test: /\.styl(us)?$/, | ||||
| 			exclude: /node_modules/, | ||||
| 			oneOf: [{ | ||||
| 				resourceQuery: /module/, | ||||
| 				use: [{ | ||||
| 					loader: 'style-loader' | ||||
| 					loader: 'vue-style-loader' | ||||
| 				}, { | ||||
| 					loader: 'css-loader', | ||||
| 					options: { | ||||
| 						modules: true, | ||||
| 						minimize: true | ||||
| 					} | ||||
| 				}, { | ||||
| 					loader: 'sass-loader', | ||||
| 					options: { | ||||
| 						importer: jsonImporter, | ||||
| 					} | ||||
| 					loader: 'stylus-loader' | ||||
| 				}] | ||||
| 			}, { | ||||
| 				test: /\.css$/, | ||||
| 				use: [{ | ||||
| 					loader: 'vue-style-loader' | ||||
| 				}, { | ||||
|  | @ -221,52 +195,79 @@ module.exports = entries.map(x => { | |||
| 					options: { | ||||
| 						minimize: true | ||||
| 					} | ||||
| 				}] | ||||
| 			}, { | ||||
| 				test: /\.(eot|woff|woff2|svg|ttf)([\?]?.*)$/, | ||||
| 				loader: 'url-loader' | ||||
| 			}, { | ||||
| 				test: /\.ts$/, | ||||
| 				exclude: /node_modules/, | ||||
| 				use: [{ | ||||
| 					loader: 'ts-loader', | ||||
| 					options: { | ||||
| 						happyPackMode: true, | ||||
| 						configFile: __dirname + '/src/client/app/tsconfig.json', | ||||
| 						appendTsSuffixTo: [/\.vue$/] | ||||
| 					} | ||||
| 				}, { | ||||
| 					loader: 'replace', | ||||
| 					query: { | ||||
| 						search: i18nReplacer.pattern.toString(), | ||||
| 						replace: 'i18nReplacement', | ||||
| 						i18n: true, | ||||
| 						lang | ||||
| 					} | ||||
| 				}, { | ||||
| 					loader: 'replace', | ||||
| 					query: { | ||||
| 						search: faPattern.toString(), | ||||
| 						replace: 'faReplacement' | ||||
| 					} | ||||
| 					loader: 'stylus-loader' | ||||
| 				}] | ||||
| 			}] | ||||
| 		}, | ||||
| 		plugins, | ||||
| 		output, | ||||
| 		resolve: { | ||||
| 			extensions: [ | ||||
| 				'.js', '.ts', '.json' | ||||
| 			], | ||||
| 			alias: { | ||||
| 				'const.styl': __dirname + '/src/client/const.styl' | ||||
| 			} | ||||
| 		}, | ||||
| 		resolveLoader: { | ||||
| 			modules: ['node_modules', './webpack/loaders'] | ||||
| 		}, | ||||
| 		cache: true, | ||||
| 		devtool: false, //'source-map',
 | ||||
| 		mode: isProduction ? 'production' : 'development' | ||||
| 	}; | ||||
| }); | ||||
| 		}, { | ||||
| 			test: /\.scss$/, | ||||
| 			exclude: /node_modules/, | ||||
| 			use: [{ | ||||
| 				loader: 'style-loader' | ||||
| 			}, { | ||||
| 				loader: 'css-loader', | ||||
| 				options: { | ||||
| 					minimize: true | ||||
| 				} | ||||
| 			}, { | ||||
| 				loader: 'sass-loader', | ||||
| 				options: { | ||||
| 					importer: jsonImporter, | ||||
| 				} | ||||
| 			}] | ||||
| 		}, { | ||||
| 			test: /\.css$/, | ||||
| 			use: [{ | ||||
| 				loader: 'vue-style-loader' | ||||
| 			}, { | ||||
| 				loader: 'css-loader', | ||||
| 				options: { | ||||
| 					minimize: true | ||||
| 				} | ||||
| 			}] | ||||
| 		}, { | ||||
| 			test: /\.(eot|woff|woff2|svg|ttf)([\?]?.*)$/, | ||||
| 			loader: 'url-loader' | ||||
| 		}, { | ||||
| 			test: /\.ts$/, | ||||
| 			exclude: /node_modules/, | ||||
| 			use: [{ | ||||
| 				loader: 'ts-loader', | ||||
| 				options: { | ||||
| 					happyPackMode: true, | ||||
| 					configFile: __dirname + '/src/client/app/tsconfig.json', | ||||
| 					appendTsSuffixTo: [/\.vue$/] | ||||
| 				} | ||||
| 			}, { | ||||
| 				loader: 'replace', | ||||
| 				query: { | ||||
| 					search: i18nPattern.toString(), | ||||
| 					replace: 'i18nReplacement', | ||||
| 					i18n: true | ||||
| 				} | ||||
| 			}, { | ||||
| 				loader: 'replace', | ||||
| 				query: { | ||||
| 					search: faPattern.toString(), | ||||
| 					replace: 'faReplacement' | ||||
| 				} | ||||
| 			}] | ||||
| 		}] | ||||
| 	}, | ||||
| 	plugins, | ||||
| 	output, | ||||
| 	resolve: { | ||||
| 		extensions: [ | ||||
| 			'.js', '.ts', '.json' | ||||
| 		], | ||||
| 		alias: { | ||||
| 			'const.styl': __dirname + '/src/client/const.styl' | ||||
| 		} | ||||
| 	}, | ||||
| 	resolveLoader: { | ||||
| 		modules: ['node_modules', './webpack/loaders'] | ||||
| 	}, | ||||
| 	cache: true, | ||||
| 	devtool: false, //'source-map',
 | ||||
| 	mode: isProduction ? 'production' : 'development' | ||||
| }; | ||||
|  |  | |||
							
								
								
									
										24
									
								
								webpack/i18n.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								webpack/i18n.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| /** | ||||
|  * Replace i18n texts | ||||
|  */ | ||||
| 
 | ||||
| export const pattern = /%i18n:([a-z0-9_\-@\.\!]+?)%/g; | ||||
| 
 | ||||
| export const replacement = (ctx, match, key) => { | ||||
| 	const client = '/src/client/app/'; | ||||
| 	let name = null; | ||||
| 
 | ||||
| 	const shouldEscape = key[0] == '!'; | ||||
| 	if (shouldEscape) { | ||||
| 		key = key.substr(1); | ||||
| 	} | ||||
| 
 | ||||
| 	if (key[0] == '@') { | ||||
| 		name = ctx.src.substr(ctx.src.indexOf(client) + client.length); | ||||
| 		key = key.substr(1); | ||||
| 	} | ||||
| 
 | ||||
| 	const path = name ? `${name}|${key}` : key; | ||||
| 
 | ||||
| 	return shouldEscape ? `%i18n:!${path}%` : `%i18n:${path}%`; | ||||
| }; | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue