Skip to content

Instantly share code, notes, and snippets.

@ethan605
Last active December 5, 2018 07:45
Show Gist options
  • Save ethan605/ea27e83821ee7d3ca0b376cfeb379b7f to your computer and use it in GitHub Desktop.
Save ethan605/ea27e83821ee7d3ca0b376cfeb379b7f to your computer and use it in GitHub Desktop.
Gulp task to convert locale json file <=> csv
/**
* I18n translations helpers
*/
// Built-in modules
import fs from 'fs';
// Gulp modules
import gulp from 'gulp';
import clean from 'gulp-clean';
import file from 'gulp-file';
// Helper modules
import csv from 'csv';
import _ from 'lodash';
const CWD = './gulp-helpers/i18n';
const INP_DIR = './src/i18n/locales';
const OUT_DIR = `${CWD}/locales`;
const INP_FILE = 'translations.inp.csv';
const OUT_FILE = 'translations.out.csv';
const LANGUAGES = ['en', 'some_other_language'];
const BASE_LANGUAGE = 'en';
const COLUMN_TITLES = ['Key path', ...LANGUAGES];
const NOT_AVAILABLE = '__n_a__';
/**
*
* Flatten paths of multiple-level nested object
* used when extracting strings from I18n localization files
*
* Input: nested object with structures like this
* ```
* {
* a: {
* b: 'c',
* d: 'e',
* },
* f: {
* g: {
* h: 'i',
* j: 'k',
* },
* },
* }
* ```
*
* Output: array of flatten paths
* ```
* [
* 'a.b',
* 'a.d',
* 'f.g.h',
* 'f.g.j',
* ]
* ```
*
* @export
* @param {Object} obj
* @param {string} [parentKey='']
* @returns {Array}
* @memberof I18nUtils
*/
function flattenPaths(obj, parentKey = '') {
return _.flatMap(obj, (value, key) => {
if (_.isString(value)) return `${parentKey}${key}`;
return flattenPaths(value, `${parentKey}${key}.`);
});
}
/**
*
* Revert process of `flattenPaths`:
* convert an array of flatten paths into an object
* that can be used as template to set values with `_.set()`
*
* Input: array of flatten paths
* ```
* [
* 'a.b',
* 'a.d',
* 'f.g.h',
* 'f.g.j',
* ]
* ```
*
* Output: template with structures like this
* ```
* {
* a: {
* b: '',
* d: '',
* },
* f: {
* g: {
* h: '',
* j: '',
* },
* },
* }
* ```
*
* @param {Object} obj
* @param {Array} [keys=[]]
* @returns
* @memberof I18nUtils
*/
function nestKeys(obj, keys = []) {
if (_.isEmpty(keys)) return;
const [firstKey, ...restKeys] = keys;
const placeholder = _.isEmpty(restKeys) ? '' : {};
if (obj[firstKey] == null) obj[firstKey] = placeholder;
nestKeys(obj[firstKey], restKeys);
}
function buildCurrentLocales() {
const localesData = _.map(LANGUAGES, lang => {
const fileData = fs.readFileSync(`${INP_DIR}/${lang}.json`);
return JSON.parse(String(fileData));
});
return _.zipObject(LANGUAGES, localesData);
}
gulp.task('i18n:clean-up', () => {
gulp.src([`${CWD}/${INP_FILE}`, `${CWD}/${OUT_FILE}`, `${OUT_DIR}/*`]).pipe(clean());
});
gulp.task('i18n:from-csv', () => {
const currentLocalesData = buildCurrentLocales();
const input = String(fs.readFileSync(`${CWD}/${INP_FILE}`));
csv.parse(input, (error, records) => {
if (error != null) {
console.warn(error);
return;
}
_.each(LANGUAGES, (lang, index) => {
const { [lang]: locales } = currentLocalesData;
_.each(records, ([path]) => nestKeys(locales, _.split(path, '.')));
_.each(records, ([path, ...langsData]) => {
const data = _.replace(_.trim(langsData[index]), /\s*\r\n/gi, '\n');
_.set(locales, path, data);
});
const output = JSON.stringify(locales, null, 2);
file(`${lang}.json`, output, { src: true }).pipe(gulp.dest(OUT_DIR));
});
});
});
gulp.task('i18n:to-csv', () => {
const locales = buildCurrentLocales();
const paths = flattenPaths(locales[BASE_LANGUAGE]);
const records = _.map(paths, path => {
const row = _.map(LANGUAGES, lang => {
const value = _.get(locales[lang], path);
return _.startsWith(value, NOT_AVAILABLE) ? '' : value;
});
return [path, ...row];
});
csv.stringify(records, { columns: COLUMN_TITLES, header: true }, (err, result) => {
file(OUT_FILE, result, { src: true }).pipe(gulp.dest(CWD));
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment