Improve i18n caching (#12030)

* fix indentation

* wip: cache i18n responses

* cache i18n browser script to disk

* typos

* misc fixes
This commit is contained in:
Matteo Pagliazzi
2020-05-05 20:31:33 +02:00
committed by GitHub
parent 446122d7b8
commit e5f1f3b279
6 changed files with 69 additions and 29 deletions

1
.gitignore vendored
View File

@@ -4,6 +4,7 @@ website/transpiled-babel/
website/common/transpiled-babel/ website/common/transpiled-babel/
node_modules node_modules
content_cache content_cache
i18n_cache
apidoc_build apidoc_build
*.swp *.swp
.idea* .idea*

View File

@@ -11,10 +11,16 @@ gulp.task('build:babel:common', () => gulp.src('website/common/script/**/*.js')
gulp.task('build:babel', gulp.parallel('build:babel:server', 'build:babel:common', done => done())); gulp.task('build:babel', gulp.parallel('build:babel:server', 'build:babel:common', done => done()));
gulp.task('build:cache', gulp.parallel(
'cache:content',
'cache:i18n',
done => done(),
));
gulp.task('build:prod', gulp.series( gulp.task('build:prod', gulp.series(
'build:babel', 'build:babel',
'apidoc', 'apidoc',
'content:cache', 'build:cache',
done => done(), done => done(),
)); ));

View File

@@ -2,7 +2,7 @@ import gulp from 'gulp';
import fs from 'fs'; import fs from 'fs';
// TODO parallelize, use gulp file helpers // TODO parallelize, use gulp file helpers
gulp.task('content:cache', done => { gulp.task('cache:content', done => {
// Requiring at runtime because these files access `common` // Requiring at runtime because these files access `common`
// code which in production works only if transpiled so after // code which in production works only if transpiled so after
// gulp build:babel:common has run // gulp build:babel:common has run
@@ -32,3 +32,32 @@ gulp.task('content:cache', done => {
done(err); done(err);
} }
}); });
gulp.task('cache:i18n', done => {
// Requiring at runtime because these files access `common`
// code which in production works only if transpiled so after
// gulp build:babel:common has run
const { BROWSER_SCRIPT_CACHE_PATH, geti18nBrowserScript } = require('../website/server/libs/i18n'); // eslint-disable-line global-require
const { langCodes } = require('../website/server/libs/i18n'); // eslint-disable-line global-require
try {
// create the cache folder (if it doesn't exist)
try {
fs.mkdirSync(BROWSER_SCRIPT_CACHE_PATH);
} catch (err) {
if (err.code !== 'EEXIST') throw err;
}
// create and save the i18n browser script for each language
langCodes.forEach(languageCode => {
fs.writeFileSync(
`${BROWSER_SCRIPT_CACHE_PATH}${languageCode}.js`,
geti18nBrowserScript(languageCode),
'utf8',
);
});
done();
} catch (err) {
done(err);
}
});

View File

@@ -13,11 +13,11 @@ const gulp = require('gulp');
if (process.env.NODE_ENV === 'production') { // eslint-disable-line no-process-env if (process.env.NODE_ENV === 'production') { // eslint-disable-line no-process-env
require('./gulp/gulp-apidoc'); // eslint-disable-line global-require require('./gulp/gulp-apidoc'); // eslint-disable-line global-require
require('./gulp/gulp-content'); // eslint-disable-line global-require require('./gulp/gulp-cache'); // eslint-disable-line global-require
require('./gulp/gulp-build'); // eslint-disable-line global-require require('./gulp/gulp-build'); // eslint-disable-line global-require
} else { } else {
require('./gulp/gulp-apidoc'); // eslint-disable-line global-require require('./gulp/gulp-apidoc'); // eslint-disable-line global-require
require('./gulp/gulp-content'); // eslint-disable-line global-require require('./gulp/gulp-cache'); // eslint-disable-line global-require
require('./gulp/gulp-build'); // eslint-disable-line global-require require('./gulp/gulp-build'); // eslint-disable-line global-require
require('./gulp/gulp-console'); // eslint-disable-line global-require require('./gulp/gulp-console'); // eslint-disable-line global-require
require('./gulp/gulp-sprites'); // eslint-disable-line global-require require('./gulp/gulp-sprites'); // eslint-disable-line global-require

View File

@@ -1,26 +1,13 @@
import _ from 'lodash'; import nconf from 'nconf';
import { import {
translations, BROWSER_SCRIPT_CACHE_PATH,
momentLangs, geti18nBrowserScript,
availableLanguages,
} from '../../libs/i18n'; } from '../../libs/i18n';
const IS_PROD = nconf.get('IS_PROD');
const api = {}; const api = {};
function geti18nBrowserScript (language) {
const langCode = language.code;
return `(function () {
if (!window) return;
window['habitica-i18n'] = ${JSON.stringify({
availableLanguages,
language,
strings: translations[langCode],
momentLang: momentLangs[langCode],
})};
})()`;
}
/** /**
* @api {get} /api/v3/i18n/browser-script Returns the i18n JS script. * @api {get} /api/v3/i18n/browser-script Returns the i18n JS script.
* @apiDescription Returns the i18n JS script to make * @apiDescription Returns the i18n JS script to make
@@ -33,14 +20,16 @@ api.geti18nBrowserScript = {
method: 'GET', method: 'GET',
url: '/i18n/browser-script', url: '/i18n/browser-script',
async handler (req, res) { async handler (req, res) {
const language = _.find(availableLanguages, { code: req.language }); if (IS_PROD) {
res.sendFile(`${BROWSER_SCRIPT_CACHE_PATH}${req.language}.js`);
} else {
res.set({
'Content-Type': 'application/javascript',
});
res.set({ const jsonResString = geti18nBrowserScript(req.language);
'Content-Type': 'application/javascript', res.status(200).send(jsonResString);
}); }
const jsonResString = geti18nBrowserScript(language);
res.status(200).send(jsonResString);
}, },
}; };

View File

@@ -4,6 +4,7 @@ import _ from 'lodash';
import shared from '../../common'; import shared from '../../common';
export const localePath = path.join(__dirname, '../../common/locales/'); export const localePath = path.join(__dirname, '../../common/locales/');
export const BROWSER_SCRIPT_CACHE_PATH = path.join(__dirname, '/../../../i18n_cache/');
// Store translations // Store translations
export const translations = {}; export const translations = {};
@@ -115,3 +116,17 @@ export const multipleVersionsLanguages = {
'pt-br': 'pt_BR', 'pt-br': 'pt_BR',
}, },
}; };
export function geti18nBrowserScript (languageCode) {
const language = _.find(availableLanguages, { code: languageCode });
return `(function () {
if (!window) return;
window['habitica-i18n'] = ${JSON.stringify({
availableLanguages,
language,
strings: translations[languageCode],
momentLang: momentLangs[languageCode],
})};
})()`;
}