UNPKG

@gctools-components/i18n-translation-webpack-plugin

Version:

Complete i18n translation solution for webpack, including code-splitting and automatic generation of translation files

154 lines (140 loc) 5.26 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = buildPo; /* * Author: National Research Council Canada * Website: http://www.nrc-cnrc.gc.ca/eng/rd/ict/ * * License: MIT * Copyright: Her Majesty the Queen in Right of Canada, as represented by * the Minister of National Research Council, 2017 * * * Build po files * This file invokes the Python module "pot-builder" to create or update * .po files based on the .pot files in the i18n directory. * * It should be invoked via npm run build:locale from the webapp folder. */ /* eslint-disable no-console */ var virtualenv = require('virtualenv'); var childProcess = require('child_process'); var path = require('path'); var fs = require('fs'); var md5File = require('md5-file'); var packagePath = require.resolve('../package.json'); var env = virtualenv(packagePath); /** * Using `virtualenv` spawn the included pot-builder python module to generate * or update .po files based on the supplied .pot files. * * @param { path: string, filename: string, languages: Array<string> } config */ function buildPo(config) { // TODO: submit MR to virtualenv to support spawnsync var pathToVirtualenvPython = path.join(env._virtualenvHome, // eslint-disable-line no-underscore-dangle 'bin', 'python'); var args = ['-m', 'build']; args.push(JSON.stringify(config)); var output = childProcess.spawnSync(pathToVirtualenvPython, args); if (output.status !== 0) { console.log('An error has occured trying to build the .po files.'); if (output.stderr) { console.log(output.stderr.toString()); } if (output.error) { console.log(output.error); throw new Error(output.error); } } if (output.stdout) { console.log(output.stdout.toString()); } } // Generate an object hash for each PO file... // TODO: doesn't webpack do this? var buildPotHash = exports.buildPotHash = function buildPotHash(i18nDir) { var generateHash = function generateHash(dir) { var files = fs.readdirSync(dir); var potHash = {}; Object.keys(files).forEach(function (f) { var filename = path.join(dir, files[f]); if (filename.indexOf('.pot') > 2) { potHash[filename] = md5File.sync(filename); } else if (fs.statSync(filename).isDirectory()) { potHash = Object.assign(generateHash(filename), potHash); } }); return potHash; }; return generateHash(i18nDir); }; /** * Test if the specified directory exists, if not create it. * @param string i18nDir Directory to test */ var ensureDirExists = exports.ensureDirExists = function ensureDirExists(i18nDir) { if (!fs.existsSync(i18nDir)) { var sep = path.sep; var initDir = path.isAbsolute(i18nDir) ? sep : ''; i18nDir.split(sep).reduce(function (parentDir, childDir) { var curDir = path.resolve(parentDir, childDir); if (!fs.existsSync(curDir)) { fs.mkdirSync(curDir); } return curDir; }, initDir); } }; /** * Scan all the .pot files to determine what .po files needs to be rebuilt. * * @param string i18nDir Directory where .pot files can be found * @param Array<String> potFiles Previous hash values to compare against * @param Array<String> languages Languages to build for */ var buildPoFiles = exports.buildPoFiles = function buildPoFiles(i18nDir, potFiles, languages) { var currentHash = buildPotHash(i18nDir); // If the .pot files were changed, rebuild the .po files. if (JSON.stringify(currentHash) !== JSON.stringify(potFiles)) { Object.keys(currentHash).forEach(function (y) { if (!potFiles[y] || potFiles[y] !== currentHash[y]) { var filename = path.relative(path.join(i18nDir, 'templates'), y); buildPo({ path: i18nDir, languages: languages, filename: filename }); } }); return buildPotHash(i18nDir); } return currentHash; }; /** * The gettext-loader module requires a file at the root of the project to * function. This method creates that file, and later deletes it. * * @param {*} rootDir Root directory of project * @param {*} i18nDir Location of i18n files * @returns { remove: () => void } Method that can be used to delete the file. */ var createGettextConfig = exports.createGettextConfig = function createGettextConfig(rootDir, i18nDir) { // Create the gettext-loader config file. // TODO: Yuck. var gtcFilename = path.join(rootDir, 'gettext.config.js'); var outputPath = '' + path.join(i18nDir, 'templates', '[filename].pot'); var gtcConfig = ['module.exports = {', ' methods: [\'__\', \'translate\'],', ' output: \'' + outputPath + '\',', ' header_prefix: \'msgid ""\\nmsgstr ""\',', ' header: {', ' \'Language\': \'en\\\\n\',', ' \'Plural-Forms\': \'nplurals=2; plural=(n != 1);\\\\n\',', ' \'MIME-Version\': \'1.0\\\\n\',', ' \'Content-Type\': \'text/plain; charset=UTF-8\\\\n\',', ' \'Content-Transfer-Encoding\': \'8bit\\\\n\'', ' }', '};']; fs.writeFileSync(gtcFilename, gtcConfig.join('\n')); return { remove: function remove() { try { fs.accessSync(gtcFilename); fs.unlinkSync(gtcFilename); // eslint-disable-next-line } catch (ex) {} } }; };