UNPKG

@pascholda1/vue-cli-plugin-i18n-csv-exchange

Version:

Vue CLI plugin to convert i18n localizations from JSON to CSV / CSV to JSON

187 lines (140 loc) 4.7 kB
const fs = require('fs'); const path = require('path'); const CSVStringifier = require('csv-stringify/sync'); const CSVParse = require('csv-parse/sync'); const _set = require('lodash/set'); module.exports = async (api, options) => { const mode = options.mode || 'JSONtoCSV'; const jsonDir = options.jsonDir || './src/locales'; const csvDir = options.csvDir || './localizations'; if (mode === 'JSONtoCSV') { convertJSONtoCSV(jsonDir, csvDir); copyStaticFiles(csvDir); } else if (mode === 'CSVtoJSON') { convertCSVtoJSON(csvDir, jsonDir); } else { throw new Error('unknown mode ' + mode); } addPackageScripts(api, jsonDir, csvDir); }; const convertJSONtoCSV = function(jsonDir, csvDir) { fs.readdirSync(jsonDir) // filename to path .map(filename => [jsonDir, filename].join('/')) // read JSON Files .map(uri => ({uri, json: readJSONFile(uri)})) // add Object paths .map(file => { file.json = addObjectPaths(file.json); return file; }) // generate CSV per locale: objPath => value .map(file => { file.csvData = generateCSVMap(file.json); return file; }) // write CSV .forEach(({uri, csvData}) => writeCSVFile(uri, csvDir, csvData)); }; const convertCSVtoJSON = function(csvDir, jsonDir) { fs.readdirSync(csvDir) .map(filename => [csvDir, filename].join('/')) .map(uri => ({ uri, content: fs.readFileSync(uri), })) .map(file => { file.parsedContent = CSVParse.parse(file.content, { columns: false, skip_empty_lines: true, }); return file; }) .forEach( ({uri, parsedContent}) => writeJSONFile(uri, jsonDir, parsedContent)); }; const addPackageScripts = function(api, jsonDir, csvDir) { let packageExt = { scripts: { 'i18n-export-csv': 'vue invoke vue-cli-plugin-i18n-exchange --mode JSONtoCSV --jsonDir ' + jsonDir + ' --csvDir ' + csvDir, 'i18n-import-csv': 'vue invoke vue-cli-plugin-i18n-exchange --mode CSVtoJSON --jsonDir ' + jsonDir + ' --csvDir ' + csvDir, }, }; api.extendPackage(packageExt); }; const readJSONFile = function(uri) { const content = fs.readFileSync(uri); return JSON.parse(content.toString()); }; const addObjectPaths = function( obj, objectPath = [], objectPathKey = '$_path') { if (Array.isArray(obj)) { obj.map((item, idx) => addObjectPaths(item, [...objectPath, idx], objectPathKey)); } else if (typeof obj === 'object') { obj[objectPathKey] = objectPath; for (const key in obj) { obj[key] = addObjectPaths(obj[key], [...objectPath, key], objectPathKey); } } return obj; }; const generateCSVMap = function( srcObject, result = {}, objectPathKey = '$_path') { if (Array.isArray(srcObject)) { srcObject.forEach(value => result = generateCSVMap(value, result)); } else if (typeof srcObject === 'object') { for (const key in srcObject) { const value = srcObject[key]; if (typeof value === 'string') { const resultKey = [ ...srcObject[objectPathKey], key, ].join('.'); result[resultKey] = value; } else { result = generateCSVMap(value, result); } } } return result; }; const writeCSVFile = function(srcFile, csvDir, csvData) { const [localeName] = srcFile.split('/').pop().split('.'); const targetFile = [csvDir, localeName].join('/') + '.csv'; if (!fs.existsSync(csvDir)) { fs.mkdirSync(csvDir); } const stringified = CSVStringifier.stringify(Object.entries(csvData)); fs.writeFileSync(targetFile, stringified); console.info( '✅ CSV file for locale "' + localeName + '" created successfully in ' + csvDir, ); }; const writeJSONFile = function(srcFileUri, jsonDir, contents) { const [locale] = srcFileUri.split('/').pop().split('.'); const targetFileUri = [jsonDir, locale].join('/') + '.json'; let result = {}; if (fs.existsSync(targetFileUri)) { result = fs.readFileSync(targetFileUri); } contents.forEach(([key, value]) => { _set(result, key, value); }); console.log(locale, targetFileUri, result); fs.writeFileSync(targetFileUri, JSON.stringify(result)); }; const copyStaticFiles = function(csvDir) { const staticDir = path.dirname(__filename) + '/static'; fs.readdirSync(staticDir) // map src & dest filename .map(filename => ({ src: [staticDir, filename].join('/'), dest: [csvDir, filename].join('/'), })) // copy files .forEach(({src, dest}) => fs.copyFileSync(src, dest)); };