diff --git a/gulpfile.ts b/gulpfile.ts index 06eaafc96..ff178582b 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -2,6 +2,7 @@ * Gulp tasks */ +import * as childProcess from 'child_process'; import * as fs from 'fs'; import * as Path from 'path'; import * as gulp from 'gulp'; @@ -10,7 +11,6 @@ import * as ts from 'gulp-typescript'; import tslint from 'gulp-tslint'; import * as glob from 'glob'; import * as es from 'event-stream'; -import * as webpack from 'webpack-stream'; import cssnano = require('gulp-cssnano'); //import * as uglify from 'gulp-uglify'; import pug = require('gulp-pug'); @@ -123,21 +123,25 @@ gulp.task('cleanall', ['clean'], cb => gulp.task('default', ['build']); gulp.task('build:client', [ - 'build:ts', 'build:js', - 'build:client:scripts', + 'build:ts', + 'build:js', + 'webpack', + 'build:client:script', 'build:client:pug', 'copy:client' ]); -gulp.task('build:client:scripts', () => - es.merge( - webpack(require('./webpack.config'), require('webpack')) - .pipe(gulp.dest('./built/web/assets/')) as any, - gulp.src('./src/web/app/client/script.js') - .pipe(replace('VERSION', JSON.stringify(version))) - //.pipe(isProduction ? uglify() : gutil.noop()) - .pipe(gulp.dest('./built/web/assets/client/')) as any - ) +gulp.task('webpack', done => { + const output = childProcess.execSync(Path.join('.', 'node_modules', '.bin', 'webpack') + ' --config webpack.config.ts', ); + console.log(output.toString()); + done(); +}); + +gulp.task('build:client:script', () => + gulp.src('./src/web/app/client/script.js') + .pipe(replace('VERSION', JSON.stringify(version))) + //.pipe(isProduction ? uglify() : gutil.noop()) + .pipe(gulp.dest('./built/web/assets/client/')) as any ); gulp.task('build:client:styles', () => @@ -149,7 +153,8 @@ gulp.task('build:client:styles', () => ); gulp.task('copy:client', [ - 'build:client:scripts' + 'build:client:script', + 'webpack' ], () => gulp.src([ './assets/**/*', @@ -165,7 +170,7 @@ gulp.task('copy:client', [ gulp.task('build:client:pug', [ 'copy:client', - 'build:client:scripts', + 'build:client:script', 'build:client:styles' ], () => gulp.src('./src/web/app/*/view.pug') diff --git a/locales/en.json b/locales/en.json new file mode 100644 index 000000000..ea6ae5b7d --- /dev/null +++ b/locales/en.json @@ -0,0 +1,3 @@ +{ + "home": "Home" +} diff --git a/locales/ja.json b/locales/ja.json new file mode 100644 index 000000000..7a7f3a2d0 --- /dev/null +++ b/locales/ja.json @@ -0,0 +1,3 @@ +{ + "home": "ホーム" +} diff --git a/package.json b/package.json index 631bb84d2..e77c1dbba 100644 --- a/package.json +++ b/package.json @@ -144,7 +144,6 @@ "uuid": "3.0.1", "vhost": "3.0.2", "webpack": "2.3.1", - "webpack-stream": "3.2.0", "websocket": "1.0.24", "whatwg-fetch": "2.0.3", "xml2json": "0.11.0" diff --git a/src/web/app/client/script.js b/src/web/app/client/script.js index 0f0fd7aa4..876d2c169 100644 --- a/src/web/app/client/script.js +++ b/src/web/app/client/script.js @@ -4,6 +4,10 @@ (() => { const head = document.getElementsByTagName('head')[0]; + // Detect user language + let lang = (navigator.languages && navigator.languages[0]) || navigator.language; + if (!/en|en\-US|ja/.test(lang)) lang = 'en'; + // Detect user agent const ua = navigator.userAgent.toLowerCase(); const isMobile = /mobile|iphone|ipad|android/.test(ua); @@ -15,7 +19,7 @@ */ function mountDesktop() { const script = document.createElement('script'); - script.setAttribute('src', `/assets/desktop/script.${VERSION}.js`); + script.setAttribute('src', `/assets/desktop/script.${VERSION}.${lang}.js`); script.setAttribute('async', 'true'); script.setAttribute('defer', 'true'); head.appendChild(script); @@ -31,7 +35,7 @@ head.appendChild(meta); const script = document.createElement('script'); - script.setAttribute('src', `/assets/mobile/script.${VERSION}.js`); + script.setAttribute('src', `/assets/mobile/script.${VERSION}.${lang}.js`); script.setAttribute('async', 'true'); script.setAttribute('defer', 'true'); head.appendChild(script); diff --git a/src/web/app/desktop/tags/ui-header-nav.tag b/src/web/app/desktop/tags/ui-header-nav.tag index 447dcf238..5ffa392f5 100644 --- a/src/web/app/desktop/tags/ui-header-nav.tag +++ b/src/web/app/desktop/tags/ui-header-nav.tag @@ -3,7 +3,7 @@
  • -

    ホーム

    +

    'i18n:home'

  • diff --git a/webpack.config.ts b/webpack.config.ts index a61e903a9..2fc8ce8a1 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -4,73 +4,94 @@ import * as webpack from 'webpack'; const StringReplacePlugin = require('string-replace-webpack-plugin'); + import version from './src/version'; const constants = require('./src/const.json'); +const languages = { + 'en': require('./locales/en.json'), + 'en-US': require('./locales/en.json'), + 'ja': require('./locales/ja.json') +}; + const env = process.env.NODE_ENV; const isProduction = env === 'production'; -const pack: webpack.Configuration = { - entry: { - 'desktop': './src/web/app/desktop/script.js', - 'mobile': './src/web/app/mobile/script.js', - 'dev': './src/web/app/dev/script.js', - 'auth': './src/web/app/auth/script.js' - }, - module: { - rules: [ - { - enforce: 'pre', - test: /\.tag$/, - exclude: /node_modules/, - loader: StringReplacePlugin.replace({ - replacements: [ - { pattern: /\$theme\-color\-foreground/g, replacement: () => constants.themeColorForeground }, - { pattern: /\$theme\-color/g, replacement: () => constants.themeColor }, - ] - }) - }, - { - test: /\.tag$/, - exclude: /node_modules/, - loader: 'riot-tag-loader', - query: { - hot: false, - style: 'stylus', - expr: false, - compact: true, - parserOptions: { - style: { - compress: true +module.exports = (Object as any).entries(languages).map(([lang, locale]) => { + const pack /*: webpack.Configuration ← fuck wrong type definition!!! */ = { + name: lang, + entry: { + 'desktop': './src/web/app/desktop/script.js', + 'mobile': './src/web/app/mobile/script.js', + 'dev': './src/web/app/dev/script.js', + 'auth': './src/web/app/auth/script.js' + }, + module: { + rules: [ + { + enforce: 'pre', + test: /\.*$/, + exclude: /node_modules/, + loader: StringReplacePlugin.replace({ + replacements: [ + { pattern: /'i18n:(.+?)'/g, replacement: (_, text) => locale[text] } + ] + }) + }, + { + enforce: 'pre', + test: /\.tag$/, + exclude: /node_modules/, + loader: StringReplacePlugin.replace({ + replacements: [ + { pattern: /\$theme\-color\-foreground/g, replacement: () => constants.themeColorForeground }, + { pattern: /\$theme\-color/g, replacement: () => constants.themeColor }, + ] + }) + }, + { + test: /\.tag$/, + exclude: /node_modules/, + loader: 'riot-tag-loader', + query: { + hot: false, + style: 'stylus', + expr: false, + compact: true, + parserOptions: { + style: { + compress: true + } } } + }, + { + test: /\.styl$/, + exclude: /node_modules/, + use: [ + { loader: 'style-loader' }, + { loader: 'css-loader' }, + { loader: 'stylus-loader' } + ] } - }, - { - test: /\.styl$/, - exclude: /node_modules/, - use: [ - { loader: 'style-loader' }, - { loader: 'css-loader' }, - { loader: 'stylus-loader' } - ] - } - ] - }, - plugins: [ - new webpack.DefinePlugin({ - VERSION: JSON.stringify(version), - THEME_COLOR: JSON.stringify(constants.themeColor) - }), - new StringReplacePlugin() - ], - output: { - filename: `[name]/script.${version}.js` + ] + }, + plugins: [ + new webpack.DefinePlugin({ + VERSION: JSON.stringify(version), + THEME_COLOR: JSON.stringify(constants.themeColor) + }), + new StringReplacePlugin() + ], + output: { + path: __dirname + '/built/web/assets', + filename: `[name]/script.${version}.${lang}.js` + } + }; + + if (isProduction) { + //pack.plugins.push(new webpack.optimize.UglifyJsPlugin()); } -}; -if (isProduction) { - //pack.plugins.push(new webpack.optimize.UglifyJsPlugin()); -} - -module.exports = pack; + return pack; +});