diff --git a/Makefile b/Makefile index 02338d2..22361c7 100644 --- a/Makefile +++ b/Makefile @@ -45,11 +45,6 @@ update-po: po/$(PACKAGE_NAME).pot msgmerge --output-file=po/$$lang.po po/$$lang.po $<; \ done -dist/po.%.js: po/%.po $(NODE_MODULES_TEST) - mkdir -p $(dir $@) - po/po2json -m po/po.empty.js -o $@.js.tmp $< - mv $@.js.tmp $@ - # # Build/Install/dist # @@ -57,7 +52,7 @@ dist/po.%.js: po/%.po $(NODE_MODULES_TEST) %.spec: %.spec.in sed -e 's/%{VERSION}/$(VERSION)/g' $< > $@ -$(WEBPACK_TEST): $(NODE_MODULES_TEST) src/lib/patternfly/_fonts.scss $(shell find src/ -type f) package.json webpack.config.js $(patsubst %,dist/po.%.js,$(LINGUAS)) +$(WEBPACK_TEST): $(NODE_MODULES_TEST) src/lib/patternfly/_fonts.scss $(shell find src/ -type f) package.json webpack.config.js NODE_ENV=$(NODE_ENV) npm run build watch: diff --git a/po/po.empty.js b/po/po.empty.js deleted file mode 100644 index 7c2d480..0000000 --- a/po/po.empty.js +++ /dev/null @@ -1,2 +0,0 @@ -/* The syntax of this line is important for po2json */ -cockpit.locale({"":{"language":"en"}}); diff --git a/po/po2json b/po/po2json deleted file mode 100755 index 690d7d0..0000000 --- a/po/po2json +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env node - -function fatal(message, code) { - console.log((filename || "html2po") + ": " + message); - process.exit(code || 1); -} - -function usage() { - console.log("usage: po2json [--module=template.js] [--output=output.js] input"); - process.exit(2); -} - -var fs, po2json, Jed, stdio; - -try { - fs = require('fs'); - po2json = require('po2json'); - Jed = require('jed'); - stdio = require('stdio'); -} catch(ex) { - fatal(ex.message, 127); /* missing looks for this */ -} - -var argi = 2; -var filename = null; - -var opts = stdio.getopt({ - module: { key: "m", args: 1, description: "Module template to include", default: "" }, - output: { key: "o", args: 1, description: "Output file", default: "" }, -}); - -if (!opts.args || opts.args.length != 1) { - usage(); -} - -parse(); - -function prepareHeader(header) { - var body, statement, plurals = header["plural-forms"], ret = null; - if (plurals) { - try { - /* Check that the plural forms isn't being sneaky since we build a function here */ - Jed.PF.parse(plurals); - } catch(ex) { - fatal("bad plural forms: " + ex.message, 1); - } - - /* A function for the front end */ - statement = header["plural-forms"]; - if (statement[statement.length - 1] != ';') - statement += ';'; - ret = 'function(n) {\nvar nplurals, plural;\n' + statement + '\nreturn plural;\n}'; - - /* Added back in later */ - delete header["plural-forms"]; - } - - /* We don't need to be transferring this */ - delete header["project-id-version"]; - delete header["report-msgid-bugs-to"]; - delete header["pot-creation-date"]; - delete header["po-revision-date"]; - delete header["last-translator"]; - delete header["language-team"]; - delete header["mime-version"]; - delete header["content-type"]; - delete header["content-transfer-encoding"]; - - return ret; -} - -/* Parse and process the po data */ -function parse() { - filename = opts.args[0]; - po2json.parseFile(opts.args[0], { "fuzzy": false }, function(err, jsonData) { - var plurals, pos; - - if (err) - fatal(err.message); - - var header = jsonData[""]; - if (header) - plurals = prepareHeader(header); - - var data = JSON.stringify(jsonData, null, 1); - - /* We know the brace in is the location to insert our function */ - if (plurals) { - pos = data.indexOf('{', 1); - data = data.substr(0, pos + 1) + "'plural-forms':" + String(plurals) + "," + data.substr(pos + 1); - } - - if (data == JSON.stringify({})) - finish(""); - else - wrap(data); - }); -} - -/* Wrap the data if desired */ -function wrap(data) { - if (opts.module) { - filename = opts.module; - fs.readFile(opts.module, { encoding: "utf-8" }, function(err, template) { - if (err) - fatal(err.message); - data = template.replace('{"":{"language":"en"}}', data); - finish(data); - }); - } else { - finish(data); - } -} - -/* Write it out */ -function finish(data) { - if (opts.output) { - fs.writeFile(opts.output, data, function(err) { - if (err) - fatal(err.message); - process.exit(0); - }); - } else { - process.stdout.write(data); - process.exit(0); - } -} diff --git a/src/lib/cockpit-po-plugin.js b/src/lib/cockpit-po-plugin.js new file mode 100644 index 0000000..4cf0f28 --- /dev/null +++ b/src/lib/cockpit-po-plugin.js @@ -0,0 +1,74 @@ +const path = require("path"); +const glob = require("glob"); +const po2json = require('po2json'); +const Jed = require('jed'); + +module.exports = class { + apply(compiler) { + compiler.hooks.emit.tapPromise( + 'CockpitPoPlugin', + compilation => Promise.all(glob.sync('po/*.po').map(f => this.buildFile(f, compilation))) + ); + } + + prepareHeader(header) { + if (!header) + return null; + + var body, statement, ret = null; + const plurals = header["plural-forms"]; + + if (plurals) { + try { + /* Check that the plural forms isn't being sneaky since we build a function here */ + Jed.PF.parse(plurals); + } catch(ex) { + fatal("bad plural forms: " + ex.message, 1); + } + + /* A function for the front end */ + statement = header["plural-forms"]; + if (statement[statement.length - 1] != ';') + statement += ';'; + ret = 'function(n) {\nvar nplurals, plural;\n' + statement + '\nreturn plural;\n}'; + + /* Added back in later */ + delete header["plural-forms"]; + } + + /* We don't need to be transferring this */ + delete header["project-id-version"]; + delete header["report-msgid-bugs-to"]; + delete header["pot-creation-date"]; + delete header["po-revision-date"]; + delete header["last-translator"]; + delete header["language-team"]; + delete header["mime-version"]; + delete header["content-type"]; + delete header["content-transfer-encoding"]; + + return ret; + } + + buildFile(po_file, compilation) { + return new Promise((resolve, reject) => { + const jsonData = po2json.parseFileSync(po_file); + const plurals = this.prepareHeader(jsonData[""]); + + let output = JSON.stringify(jsonData, null, 1); + + // We know the brace in is the location to insert our function + if (plurals) { + pos = output.indexOf('{', 1); + output = output.substr(0, pos + 1) + "'plural-forms':" + String(plurals) + "," + output.substr(pos + 1); + } + + // wrap JSON output into cockpit.locale() call + output = 'cockpit.locale(' + output + ');\n'; + + const lang = path.basename(po_file).slice(0, -3) + compilation.assets['po.' + lang + '.js'] = { source: () => output, size: () => output.length }; + resolve(); + }); + }; +}; diff --git a/webpack.config.js b/webpack.config.js index 92035c3..f02c0b9 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,11 +1,14 @@ const path = require("path"); const childProcess = require('child_process'); + const copy = require("copy-webpack-plugin"); const extract = require("mini-css-extract-plugin"); const TerserJSPlugin = require('terser-webpack-plugin'); const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); -const webpack = require("webpack"); const CompressionPlugin = require("compression-webpack-plugin"); +const CockpitPoPlugin = require("./src/lib/cockpit-po-plugin"); + +const webpack = require("webpack"); const nodedir = path.resolve((process.env.SRCDIR || __dirname), "node_modules"); @@ -20,7 +23,8 @@ const copy_files = [ const plugins = [ new copy({ patterns: copy_files }), - new extract({filename: "[name].css"}) + new extract({filename: "[name].css"}), + new CockpitPoPlugin(), ]; /* Only minimize when in production mode */