reimplemented l10n using dynamic import() (#1012)

this should greatly reduce the complexity of the l10n code
and build pipeline and eliminate the most common error
seen in sentry logs (no translate function)
This commit is contained in:
Danny Coates 2018-11-20 06:50:59 -08:00 committed by Donovan Preston
parent 5afa4e5c9b
commit 1e62aa976d
28 changed files with 145 additions and 280 deletions

View file

@ -15,16 +15,6 @@ function chunkFileNames(compilation) {
}
class AndroidIndexPlugin {
apply(compiler) {
const assets = {};
compiler.hooks.compilation.tap(NAME, compilation => {
compilation.hooks.moduleAsset.tap(NAME, (mod, file) => {
if (mod.userRequest) {
assets[
path.join(path.dirname(file), path.basename(mod.userRequest))
] = file;
}
});
});
compiler.hooks.emit.tap(NAME, compilation => {
const files = chunkFileNames(compilation);
const page = html`
@ -36,9 +26,8 @@ class AndroidIndexPlugin {
name="viewport"
content="width=device-width, initial-scale=1"
/>
<base href="file:///android_asset/" />
<link href="${files['app.css']}" rel="stylesheet" />
<script src="${files['vendor.js']}"></script>
<script src="${assets['public/locales/en-US/send.ftl']}"></script>
<script src="${files['android.js']}"></script>
</head>
<body></body>

View file

@ -1,62 +0,0 @@
const { FluentResource } = require('fluent/compat');
const fs = require('fs');
function toJSON(resource) {
return JSON.stringify(Array.from(resource));
}
module.exports = function(source) {
const localeExp = /([^/]+)\/[^/]+\.ftl$/;
const result = localeExp.exec(this.resourcePath);
const locale = result && result[1];
if (!locale) {
throw new Error(`couldn't find locale in: ${this.resourcePath}`);
}
// Parse the current language's translation file.
const locResource = FluentResource.fromString(source);
let enResource;
// If the current language is not en-US, also parse en-US to provide a
// fallback for missing translations.
if (locale !== 'en-US') {
const en_ftl = fs.readFileSync(
require.resolve('../public/locales/en-US/send.ftl'),
'utf8'
);
enResource = FluentResource.fromString(en_ftl);
}
return `
module.exports = \`
if (typeof window === 'undefined') {
var fluent = require('fluent');
}
(function () {
let bundles = [
['${locale}', ${toJSON(locResource)}],
${enResource ? `['en-US', ${toJSON(enResource)}]` : ''}
].map(([locale, entries]) => {
let bundle = new fluent.FluentBundle(locale, {useIsolating: false});
bundle.addResource(new fluent.FluentResource(entries));
return bundle;
});
function translate(id, data) {
for (let bundle of bundles) {
if (bundle.hasMessage(id)) {
let message = bundle.getMessage(id);
return bundle.format(message, data);
}
}
}
if (typeof window === 'undefined') {
module.exports = translate;
}
else {
window.translate = translate;
}
})();
\``;
};

View file

@ -1,33 +0,0 @@
/*
This code is included by both the server and frontend via
common/locales.js
When included from the server the export will be the function.
When included from the frontend (via webpack) the export will
be an object mapping ftl files to js files. Example:
"public/locales/en-US/send.ftl":"public/locales/en-US/send.6b4f8354.js"
*/
const fs = require('fs');
const path = require('path');
function kv(d) {
return `"${d}": require('../public/locales/${d}/send.ftl')`;
}
module.exports = function() {
const dirs = fs.readdirSync(path.join(__dirname, '..', 'public', 'locales'));
const code = `
module.exports = {
translate: function (id, data) { return window.translate(id, data) },
${dirs.map(kv).join(',\n')}
};`;
return {
code,
dependencies: dirs.map(d =>
require.resolve(`../public/locales/${d}/send.ftl`)
),
cacheable: true
};
};

View file

@ -1,17 +1,9 @@
# Custom Loaders
## Fluent Loader
The fluent loader "compiles" `.ftl` files into `.js` files directly usable by both the frontend and server for localization.
## Generate Asset Map
This loader enumerates all the files in `assets/` so that `common/assets.js` can provide mappings from the source filename to the hashed filename used on the site.
## Generate L10N Map
This loader enumerates all the ftl files in `public/locales` so that the fluent loader can create it's js files.
## Version Plugin
Creates a `version.json` file that gets exposed by the `/__version__` route from the `package.json` file and current git commit hash.