diff --git a/gulp/tasks/i18next.js b/gulp/tasks/i18next.js index f7eb9bd44..396165920 100644 --- a/gulp/tasks/i18next.js +++ b/gulp/tasks/i18next.js @@ -1,10 +1,10 @@ -import _ from 'lodash'; import fs from 'fs'; import gulp from 'gulp'; import gutil from 'gulp-util'; import sort from 'gulp-sort'; import i18nextScanner from 'i18next-scanner'; import table from 'text-table'; +import { languages } from '../../i18n.config'; const appConfig = { src: [ @@ -57,20 +57,7 @@ const webConfig = { debug: false, sort: false, removeUnusedKeys: true, - lngs: [ - 'en', // English (default) - 'cs', // Czech - 'de', // German - 'es', // Spanish - 'fr', // French - 'hu', // Hungarian - 'it', // Italian - 'ja', // Japanese - 'pt-br', // Portuguese (Brazil) - 'ru', // Russian - 'zh-cn', // Simplified Chinese - 'zh-tw' // Traditional Chinese - ], + lngs: languages, defaultValue: (lng, ns, key) => { if (lng === 'en') { return key; // Use key as value for base language @@ -100,7 +87,7 @@ const webConfig = { function customTransform(file, enc, done) { const parser = this.parser; const content = fs.readFileSync(file.path, enc); - let tableData = [ + const tableData = [ ['Key', 'Value'] ]; @@ -115,7 +102,7 @@ function customTransform(file, enc, done) { }); } - if (_.size(tableData) > 1) { + if (tableData.length > 1) { const text = table(tableData, { 'hsep': ' | ' }); gutil.log('i18next-scanner:', file.relative + '\n' + text); } else { diff --git a/webpack.webconfig.i18n.js b/i18n.config.js similarity index 100% rename from webpack.webconfig.i18n.js rename to i18n.config.js diff --git a/src/app/api/api.i18n.js b/src/app/api/api.i18n.js deleted file mode 100644 index 3d10444c1..000000000 --- a/src/app/api/api.i18n.js +++ /dev/null @@ -1,111 +0,0 @@ -import _ from 'lodash'; -import fs from 'fs'; -import path from 'path'; -import settings from '../config/settings'; -import logger from '../lib/logger'; - -const log = logger('api:i18n'); - -export const getAcceptedLanguage = (req, res) => { - let headers = req.headers || {}; - let httpAccept = headers['accept-language'] || ''; - - // Tags for the Identification of Languages (http://www.ietf.org/rfc/rfc1766.txt) - // - // The syntax of this tag in RFC-822 EBNF is: - // - // Language-Tag = Primary-tag *( "-" Subtag ) - // Primary-tag = 1*8ALPHA - // Subtag = 1*8ALPHA - - let values = httpAccept.split(',') || []; - let acceptedList = []; - _.each(values, (val) => { - let matches = val.match(/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i); - if (!matches) { - return; - } - let lang = matches[1]; - let qval = Number(matches[4]) || Number(1.0); - acceptedList.push({ - lang: lang.toLowerCase(), - qval: qval - }); - }); - - // In decreasing order of preference - let sortedLngs = _.chain(acceptedList) - .sortBy((o) => o.qval) - .reverse() - .map('lang') - .value(); - - let preferred, match; - - // 1. Look through sorted list and use first one that exactly matches our languages - match = 'exact'; - preferred = _.find(sortedLngs, (lang) => { - return _.contains(settings.supportedLngs, lang); - }); - - // 2. Look through sorted list again and use first one that partially matches our languages - if (!preferred) { - match = 'partial'; - _.some(sortedLngs, (lang) => { - preferred = _.find(settings.supportedLngs, (supportedLng) => { - return supportedLng.indexOf(lang) === 0; - }); - - return !!preferred; - }); - } - - // 3. Fallback to default language that matches nothing - if (!preferred) { - match = 'none'; - preferred = settings.supportedLngs[0]; - } - - const result = { - acceptedList: acceptedList, - sortedLngs: sortedLngs, - supportedLngs: settings.supportedLngs, - preferred: preferred, - match: match - }; - log.debug(`getAcceptedLanguage: ${JSON.stringify(result)}`); - - res.send(preferred); -}; - -export const saveMissing = (req, res) => { - let lng = req.params.__lng__; - let ns = req.params.__ns__; - - let mergedFile = path.join(settings.assets.web.path, 'i18n', lng, ns + '.json'); - let mergedObject = JSON.parse(fs.readFileSync(mergedFile, 'utf8')); - - let savedMissingFile = path.join(settings.assets.web.path, 'i18n', lng, ns + '.savedMissing.json'); - let savedMissingObject = req.body; - - // Copy all of the properties in the sendMissing object over to the merged object - _.extend(mergedObject, savedMissingObject); - - // Sort object by key - let sortedObject = {}; - let sortedKeys = _.keys(mergedObject).sort(); - _.each(sortedKeys, (key) => { - sortedObject[key] = mergedObject[key]; - }); - let prettyJSON = JSON.stringify(sortedObject, null, 4); // space=4 - - fs.writeFile(savedMissingFile, prettyJSON, (err) => { - if (err) { - log.error(`err=${err}`); - } else { - log.debug(`Saved missing ${JSON.stringify(savedMissingObject)} to "${savedMissingFile}"`); - } - }); - - res.send({ 'reply': 'ok' }); -}; diff --git a/src/app/api/index.js b/src/app/api/index.js index e88954695..c411fcd28 100644 --- a/src/app/api/index.js +++ b/src/app/api/index.js @@ -1,7 +1,6 @@ export * as version from './api.version'; export * as state from './api.state'; export * as gcode from './api.gcode'; -export * as i18n from './api.i18n'; export * as controllers from './api.controllers'; export * as commands from './api.commands'; export * as events from './api.events'; diff --git a/src/app/app.js b/src/app/app.js index 32c3a1358..43057262d 100644 --- a/src/app/app.js +++ b/src/app/app.js @@ -301,10 +301,6 @@ const appMain = () => { app.post(urljoin(settings.route, 'api/watch/files'), api.watch.getFiles); app.get(urljoin(settings.route, 'api/watch/file'), api.watch.readFile); app.post(urljoin(settings.route, 'api/watch/file'), api.watch.readFile); - - // I18n - app.get(urljoin(settings.route, 'api/i18n/acceptedLng'), api.i18n.getAcceptedLanguage); - app.post(urljoin(settings.route, 'api/i18n/sendMissing/:__lng__/:__ns__'), api.i18n.saveMissing); } // page diff --git a/src/app/config/settings.base.js b/src/app/config/settings.base.js index 801a38b38..96bad44c5 100644 --- a/src/app/config/settings.base.js +++ b/src/app/config/settings.base.js @@ -1,5 +1,6 @@ import path from 'path'; import pkg from '../../package.json'; +import { languages } from '../../../i18n.config'; // RCFile const RCFILE = '.cncrc'; @@ -95,21 +96,6 @@ export default { saveUninitialized: true } }, - // Supported languages - supportedLngs: [ - 'en', // English (default) - 'cs', // Czech - 'de', // German - 'es', // Spanish - 'fr', // French - 'hu', // Hungarian - 'it', // Italian - 'ja', // Japanese - 'pt-br', // Portuguese (Brazil) - 'ru', // Russian - 'zh-cn', // Simplified Chinese - 'zh-tw' // Traditional Chinese - ], siofu: { // SocketIOFileUploader dir: './tmp/siofu' }, @@ -131,20 +117,7 @@ export default { // default namespace used if not passed to translation function defaultNS: 'resource', - whitelist: [ - 'en', // English (default) - 'cs', // Czech - 'de', // German - 'es', // Spanish - 'fr', // French - 'hu', // Hungarian - 'it', // Italian - 'ja', // Japanese - 'pt-br', // Portuguese (Brazil) - 'ru', // Russian - 'zh-cn', // Simplified Chinese - 'zh-tw' // Traditional Chinese - ], + whitelist: languages, // array of languages to preload preload: [], diff --git a/src/app/config/settings.js b/src/app/config/settings.js index 4df359ab8..06ddbaceb 100644 --- a/src/app/config/settings.js +++ b/src/app/config/settings.js @@ -1,4 +1,4 @@ -import _ from 'lodash'; +import merge from 'lodash/merge'; import base from './settings.base'; import development from './settings.development'; import production from './settings.production'; @@ -7,9 +7,9 @@ const env = process.env.NODE_ENV || 'production'; // Ensure production environme const settings = {}; if (env === 'development') { - _.merge(settings, base, development, { env: env }); + merge(settings, base, development, { env: env }); } else { - _.merge(settings, base, production, { env: env }); + merge(settings, base, production, { env: env }); } export default settings; diff --git a/src/web/config/settings.js b/src/web/config/settings.js index f01493a40..db0433fa2 100644 --- a/src/web/config/settings.js +++ b/src/web/config/settings.js @@ -36,20 +36,8 @@ const settings = { // default namespace used if not passed to translation function defaultNS: 'resource', - whitelist: [ - 'en', // English (default) - 'cs', // Czech - 'de', // German - 'es', // Spanish - 'fr', // French - 'hu', // Hungarian - 'it', // Italian - 'ja', // Japanese - 'pt-br', // Portuguese (Brazil) - 'ru', // Russian - 'zh-cn', // Simplified Chinese - 'zh-tw' // Traditional Chinese - ], + // @see webpack.config.i18n.js + whitelist: process.env.I18N.languages, // array of languages to preload preload: [], diff --git a/webpack.webconfig.development.js b/webpack.webconfig.development.js index 4ef29ed03..dfe8bdf6f 100644 --- a/webpack.webconfig.development.js +++ b/webpack.webconfig.development.js @@ -14,7 +14,7 @@ const HtmlWebpackPluginAddons = require('html-webpack-plugin-addons'); const nib = require('nib'); const stylusLoader = require('stylus-loader'); const baseConfig = require('./webpack.webconfig.base'); -const languages = require('./webpack.webconfig.i18n').languages; +const languages = require('./i18n.config').languages; const pkg = require('./package.json'); const timestamp = new Date().getTime(); @@ -48,7 +48,10 @@ const webpackConfig = Object.assign({}, baseConfig, { new webpack.DefinePlugin({ 'process.env': { // This has effect on the react lib size - NODE_ENV: JSON.stringify('development') + NODE_ENV: JSON.stringify('development'), + I18N: JSON.stringify({ + languages: languages + }) } }), new webpack.HotModuleReplacementPlugin(), diff --git a/webpack.webconfig.production.js b/webpack.webconfig.production.js index d915ffa20..b93e0a4f6 100644 --- a/webpack.webconfig.production.js +++ b/webpack.webconfig.production.js @@ -15,7 +15,7 @@ const HtmlWebpackPluginAddons = require('html-webpack-plugin-addons'); const nib = require('nib'); const stylusLoader = require('stylus-loader'); const baseConfig = require('./webpack.webconfig.base'); -const languages = require('./webpack.webconfig.i18n').languages; +const languages = require('./i18n.config').languages; const pkg = require('./package.json'); // Use publicPath for production @@ -55,7 +55,10 @@ const webpackConfig = Object.assign({}, baseConfig, { new webpack.DefinePlugin({ 'process.env': { // This has effect on the react lib size - NODE_ENV: JSON.stringify('production') + NODE_ENV: JSON.stringify('production'), + I18N: JSON.stringify({ + languages: languages + }) } }), new webpack.NoEmitOnErrorsPlugin(),